shell study[include awk]

while [[ $sum -gt 0 ]];do
//to do
done;

--------------------------

if ....; then
....
elif ....; then
....
else
....
fi

-------------------------

位置参数 $1, $2,..., $N,$#代表了命令行的参数数量, $0代表了脚本的名字
-eq   等于
-ne    不等于
-gt    大于
-lt    小于
-le    小于等于
-ge   大于等于
-z    空串
=    两个字符相等
!=    两个字符不等
-n    非空串

------------------------------------------------------

mutian@mutian:~/soft/compile$ who |wc --help
Usage: wc [OPTION]... [FILE]...
  or:  wc [OPTION]... --files0-from=F
Print newline, word, and byte counts for each FILE, and a total line if
more than one FILE is specified.  With no FILE, or when FILE is -,
read standard input.  A word is a non-zero-length sequence of characters
delimited by white space.
The options below may be used to select which counts are printed, always in
the following order: newline, word, character, byte, maximum line length.
  -c, --bytes            print the byte counts
  -m, --chars            print the character counts
  -l, --lines            print the newline counts
      --files0-from=F    read input from the files specified by
                           NUL-terminated names in file F;
                           If F is - then read names from standard input
  -L, --max-line-length  print the length of the longest line
  -w, --words            print the word counts
      --help     display this help and exit
      --version  output version information and exit

Report wc bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'wc invocation'

mutian@mutian:~/soft/compile$ who
mutian   tty7         2015-12-28 10:24
mutian   pts/0        2015-12-29 10:10 (:0.0)
mutian@mutian:~/soft/compile$ who |wc -l
2
mutian@mutian:~/soft/compile$ who |wc -c
85
mutian@mutian:~/soft/compile/test$ cat > nusers
who |wc -l
^D
mutian@mutian:~/soft/compile/test$ cat nusers
who |wc -l
mutian@mutian:~/soft/compile/test$ chmod +x nusers
mutian@mutian:~/soft/compile/test$ ./nusers
2

shell 执行一个程序时,linux内核会起一个进程,内核知道如何执行编译型程序,shell脚本并发编译型程序,
当内核执行它时会无法执行,并返回“不是可执行文件”的错误信息。shell收到该信息那么判断该程序不是编译型程序,
那么就一定是shell脚本,接着启动/bin/sh来执行该程序

#!/bin/sh
指定使用什么类型的shell执行

$ cat command.sh
#!/bin/sh
echo hehe
$ ./command.sh | tee a.log
则实际执行的是以下命令
/bin/sh command.sh |tee a.log

-----------------------------------------------------------------------------

tr - translate or delete characters

-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr
-c或——complerment:取代所有不属 于第一字符集的字符; -d或——delete:删除所有属于第一字符集的字符; -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示; -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

来自: http://man.linuxde.net/tr

格式:  tr [OPTION]... SET1 [SET2]

-c或——complerment:取代所有不属于第一字符集的字符;
-d或——delete:删除所有属于第一字符集的字符;
-s或--squeeze-repeats:把连续重复的字符以单独一个字符表示;
-t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。

mutian@mutian:~/soft/compile/test$ cat temp
abdcd
kdfjalsd
mutian@mutian:~/soft/compile/test$ tr -d a < temp     //删除某个字符
bdcd
kdfjlsd

mutian@mutian:~/soft/compile/test$ tr  a x < temp    //替换某个字符
xbdcd
kdfjxlsd

mutian@mutian:~/soft/compile/test$ tr 'ab' '12' < temp   //由此看来,它是一一映射的替换
12dcd
kdfj1lsd

mutian@mutian:~/soft/compile/test$ tr  ab x < temp    //替换多个字符
xxdcd
kdfjxlsd

mutian@mutian:~/soft/compile/test$ tr  'a-z' "A-Z" < temp       // 小写换成大写
ABDCD
KDFJALSD
mutian@mutian:~/soft/compile/test$ cat temp
abbbbdcd
kdfjalsd
mutian@mutian:~/soft/compile/test$ tr -s b < temp  //删除重复出现的字符序列,只保留第一个字符
abdcd
kdfjalsd
mutian@mutian:~/soft/compile/test$ echo sdfj12ksdk3sd4sd5e6 | tr -d '0-9'
sdfjksdksdsde
mutian@mutian:~/soft/compile/test$ echo sdfj12ksdk3sd4sd5e6 | tr -cd '0-9 \n'
123456

-------------------------------------------------------------------------------

a=1;
b=5
c=9

((a=a+1))
echo $a

a=$((a+1,b++,c++))
echo $a,$b,$c

((a>1)) && echo "a>1" 
((a<1)) && echo "a<1"


a=1
total=0
echo a reset to $a

while((a<=100))
do
  ((total=total+a, a++))
done

echo total:$total

result=$((3*(2+5)))
echo result:$result

---------------------------------------------------------------------------------

 

#!/bin/bash
echo \$USER:$USER
echo -e "\$#:"$#   # -e enable interpretation of backslash escapes
echo -e "\$0:$0"
echo -e "\$1:"$1
set -x   # open trace
echo -----------------------------
set +x   #close trace

u=hello
readonly u   # variable read only
v="world !" # If has space in the string. There is no space before and after =
echo $u
echo $v
w=$u$v
x="$u $v           fuck"
echo $w
echo $x
echo $u $v
unset x       # delete variable
echo ---------------------------

echo 'Input a number between 1 to 4'
echo -n 'Your number is:'
read aNum
case $aNum in
  1)  echo 'You select 1'
  ;;     # same as break, but it can't be removed
  2)  echo 'You select 2'
  ;;
  3)  echo 'You select 3'
  ;;
  4)  echo 'You select 4'
  ;;
  -h) echo do it by yourself
  ;;
  *)  echo 'You do not select a number between 1 to 4'
  ;;
  esac

echo ------------------------------

value=10
x='a{value}db\$a'  
y="a${value}db\$a"
z=a${value}db\$a
echo x:$x
echo y:$y
echo z:$z
x="abcdefgh"
echo ${#x}  # output length of string
echo ${x:2:4}  # extra sub string
echo -n "no new line"
echo ------------------------

printf  "i=%d string:%s, output=0x%x\n" 5 $u  1024
printf "%s\n"  abc def ghi
printf "%s %s\n"  abc def ghi
echo -e "input value1:\c" 
read value1
echo $value1

echo -n "input value2:"   # do not output the trailing newline
value2=sdf
read value2
echo $value2


#a=123
if [ "$value1" == "$value2" ]; then  # if not add test, it may has error when value is null
  echo value1 == value2
elif [ -n "$a" ] ; then   # Judge whether $a has a value. test empty string with -z
  echo ${a}sdx            # In order to avoid ambiguous, use { }
elif [ $# -gt 0 ] ; then
  echo "\$# > 0"
elif [ -x "./test.sh" ]; then
  echo "./test.sh x"
elif [ -f "./test.sh" ]; then
  echo has ./test.sh
else 
  echo end if
fi
echo ----------------------------


echo test for
for index in $*      # $* is the parameter list
do  
 echo $index
done
echo ------------------------------

echo rrrrrrrr
echo "Your choice?"         # ???????????????
select var in 6753 6752 6795; do
break
done

echo ssssssssss
echo $var
echo ------------------------------

current=`date`        # command replace
echo current:$current
echo `who`
val=`expr 2 + 2`
echo "total value : $val"
echo ------------------------------------

#array
array_name=(a1 b2 c3 d4 e5)
echo ${array_name[*]}
echo ${array_name[@]}
array_name[1]=b22
value=${array_name[1]}
echo $value

length=${#array_name[*]}  # ${#array_name[@]}
echo $length
unit_length=${#array_name[1]}
echo $unit_length
echo ------------------------------------

#block comment
: '
echo 1
echo 2
'
echo end comment 1

:<<!
echo 3
echo 4
!

:<<eof
echo 5
echo 6
eof

echo 11111111111
:() {


echo 2222222222222

}
echo --------------------------------

echo Pick a platform:
echo "1. 6752"
echo "2. 6753"
echo "3. 6795"
echo -n "which would you like:"   # -n: do not output the trailing newline
read pcode

platform=
if [ "$pcode"test = 1test ]; then  # if has no test, it will fail when pcode is null
  platform=6752crc
elif [ "$pcode"test = 2test ]; then
  platform=6753crc
elif [ "$pcode"test = 3test ]; then
  platform=6795crc
else
  echo invalid platform
  exit 1
fi

echo You have selected $platform
echo ------------------------------

 

 

 

 

-e                          文件存在
-a                          文件存在(已被弃用)
-f                          被测文件是一个regular文件(正常文件,非目录或设备)
-s                          文件长度不为0
-d                          被测对象是目录
-b                          被测对象是块设备
-c                          被测对象是字符设备
-p                          被测对象是管道
-h                          被测文件是符号连接
-L                          被测文件是符号连接
-S(大写)                    被测文件是一个socket
-t                          关联到一个终端设备的文件描述符。用来检测脚本的stdin[-t0]或[-t1]是一个终端
-r                          文件具有读权限,针对运行脚本的用户
-w                          文件具有写权限,针对运行脚本的用户
-x                          文件具有执行权限,针对运行脚本的用户
-u                          set-user-id(suid)标志到文件,即普通用户可以使用的root权限文件,通过chmod +s file实现
-k                          设置粘贴位
-O                          运行脚本的用户是文件的所有者
-G                          文件的group-id和运行脚本的用户相同
-N                          从文件最后被阅读到现在,是否被修改

f1 -nt f2                   文件f1是否比f2新
f1 -ot f2                   文件f1是否比f2旧
f1 -ef f2                   文件f1和f2是否硬连接到同一个文件

二元比较操作符,比较变量或比较数字

整数比较:
-eq                       等于            if [ "$a" -eq "$b" ]
-ne                       不等于          if [ "$a" -ne "$b" ]
-gt                       大于            if [ "$a" -gt "$b" ]
-ge                       大于等于        if [ "$a" -ge "$b" ]
-lt                       小于            if [ "$a" -lt "$b" ]
-le                       小于等于        if [ "$a" -le "$b" ]

<                         小于(需要双括号)           (( "$a" < "$b" ))
<=                        小于等于(...)                (( "$a" <= "$b" ))
>                         大于(...)                    (( "$a" > "$b" ))
>=                        大于等于(...)                (( "$a" >= "$b" ))


字符串比较:
=                         等于           if [ "$a" = "$b" ]
==                        与=等价
!=                        不等于         if [ "$a" = "$b" ]
<                         小于,在ASCII字母中的顺序:
                          if [[ "$a" < "$b" ]]
                          if [ "$a" \< "$b" ]         #需要对<进行转义
>                         大于

-z                        字符串为null,即长度为0
-n                        字符串不为null,即长度不为0

 

$0 这个程式的执行名字
$n 这个程式的第n个参数值,n=1..9
$* 这个程式的所有参数,此选项参数可超过9个。
$# 这个程式的参数个数
$$ 这个程式的PID(脚本运行的当前进程ID号)
$! 执行上一个背景指令的PID(后台运行的最后一个进程的进程ID号)
$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$- 显示shell使用的当前选项,与set命令功能相同
$@ 跟$*类似,但是可以当作数组用

------------------------------------------------------------------

return and echo in function 

需要说明的是shell的返回值和c语言里面的不一样,它只是一个返回码。

比较推荐的做法是使用echo 返回值

格式:exit n
退出。设置退出码为n。(Cause the shell to exit with a status of n.)

格式:exit
退出。退出码不变,即为最后一个命令的退出码。(If n is omitted, the exit status is that of the  last  command executed. )
退出码(exit status,或exit code)的约定:
0表示成功(Zero - Success)
非0表示失败(Non-Zero  - Failure)
1表示参数不正确
2表示用法不当(Incorrect Usage)
127表示命令没有找到(Command Not Found)
126表示不是可执行的(Not an executable)
>=128 信号产生果你用 脚本 a 调用 脚本b ,要在a中判断b是否正常返回,就是根据 exit 0 or 1 来识别。 执行完b后, 判断 $? 就是返回值

#!/bin/bash
sum()
{
  return $(($1-$2))
}

minus()
{
  echo $(($1+$2))
}

sum 7 5
echo $?   # get the return value

c=$(minus 7 5)
echo $c   # get the echo value

2

12

#!/bin/bash
function add()
{
   sum=$(($1+$2))
   echo sum:$sum
   return $sum    #return is the return status code
}

function minus()
{
   minus=$(($1-$2))
   echo $minus    # echo to return the value as in c language
}

add 5 2
echo "\$?="$? 

echo -----------------

echo_minux=$(minus 7 3)
echo $echo_minux

函数return一般是返回状态码(0代表正确,其它值代表不同类型的错误),使用$?去获得。

函数echo 则返回函数的计算结果

---------------------------------------------------------------------------------------------------

(())用于数学计算

    语法:
    ((表达式1,表达式2…))
    特点:
    1、在双括号结构中,所有表达式可以像c语言一样,如:a++,b--等。
    2、在双括号结构中,所有变量可以不加入:“$”符号前缀。
    3、双括号可以进行逻辑运算,四则运算
    4、双括号结构 扩展了for,while,if条件测试运算
    5、支持多个表达式运算,各个表达式之间用“,”分开

a=1;
b=5;
c=9;

((a=a+1));
echo $a;

a=$((a+1,b++,c++));
echo $a,$b,$c

((a>1)) && echo "a>1" 
((a<1)) && echo "a<1"


a=1
total=0
echo a reset to $a

while((a<=100))
do
  ((total=total+a, a++))
done

echo total:$total

result=$((3*(2+5)))
echo result:$result

mutian@mutian:~/soft/compile/test$ ./z.sh
2
9,6,10
a>1
a reset to 1
total:5050
result:21

------------------------------------------

 比较两个字符串是否相等的办法是:
if [ "$test"x = "test"x ]; then
注意到"$test"x最后的x,这是特意安排的,因为当$test为空的时候,上面的表达式就变成了x = testx,显然是不相等的。而如果没有这个x,表达式就会报错:[: =: unary operator expected

----------------------------------------------------------------
n>&m表示使文件描述符n成为输出文件描述符m的副本。这样做的好处是,有的时候你查找文件的时候很容易产生无用的信息

> 默认为标准输出重定向1,即">"与 "1>" 相同
2>&1 意思是把 标准错误输出 重定向到 标准输出.
&>file 意思是把 标准输出 和 标准错误输出 都重定向到文件file中

rm -f $(find . -name core) & > /dev/null 

make 2>&1 | tee log.txt

| 管道
管道的作用是提供一个通道,将上一个程序的标准输出重定向到下一个程序作为下一个程序的标准输入。
通常使用管道的好处是一方面形式上简单,另一方面其执行效率要远高于使用临时文件。
这里使用管道的目的是将make程序的输出重定向到下一个程序,其最终目的是用来将输出log存入文件中。

tee
tee从标准输入中读取,并将读入的内容写到标准输出以及文件中。

 

cat food >file 2>&1 :标准输出被重定向到文件file,然后错误输出也重定向到和标准输出一样,所以也错误输出到文件file。

--------------------------------------------------------------------------------

index=7000000
while ((index >= 0))
do
  echo $((index--))
done

  mutian@mutian:~/soft/compile/test/test$ ./t.sh 1>file &
[1] 5980
mutian@mutian:~/soft/compile/test/test$
mutian@mutian:~/soft/compile/test/test$
[1]+  Done                    ./t.sh > file
mutian@mutian:~/soft/compile/test/test$
---------------------------

 mutian@mutian:~/soft/compile/test/test$ ./t.sh 1>file &
[1] 5980
mutian@mutian:~/soft/compile/test/test$ exit      //脚本仍然能会进行完毕,但是如果点击x关闭该终端则脚本终止

---------------------------

mutian@mutian:~/soft/compile/test/test$ nohup ./t.sh  1>file 2>&1 &     // 将脚本作为后台服务运行,有信号(比如关闭终端窗口)也不会中断
[1] 14439
mutian@mutian:~/soft/compile/test/test$    

---------------------------------------------------------------------------

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。

单引号字符串的限制:
    单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
    单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

双引号的优点:
    双引号里可以有变量
    双引号里可以出现转义字符
-------------------------------------------------------------------

Shell 函数的定义格式如下:
[function] function_name () {
    list of commands
    [ return value ]
}

函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。
Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。
如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。
--------------------------------------------------------------------------

awk [-F  field-separator]  '[/pattern/]+commands'  input-file(s)

awk  [-F  field-separator]   '[/pattern/][{commands}]'   input-file(s)
awk工作流程是这样的:读入有'\n'换行符分割的一行记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,即当前整个行。$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键"

-F 指定分割符(default: empty space)

mutian@mutian:~/soft/compile/test$ last -n 5
mutian   pts/2        :0               Fri Jan  8 10:51   still logged in   
mutian   pts/1        :0               Fri Jan  8 09:51   still logged in   
reboot   system boot  3.5.0-54-generic Thu Jan  7 18:06 - 16:24  (22:17)    
mutian   pts/1        :0.0             Thu Jan  7 18:04 - 18:06  (00:02)    
mutian   pts/5        :0.0             Thu Jan  7 17:46 - 18:03  (00:16)    

wtmp begins Mon Jan  4 09:48:54 2016
mutian@mutian:~/soft/compile/test$ last -n 5 |awk '{print $1}'
mutian
mutian
reboot
mutian
mutian

wtmp

mutian@mutian:~/soft/compile/test$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mutian@mutian:~/soft/compile/test$ awk  -F ':'  '{print $1"\t"$7}'  /etc/passwd
root    /bin/bash
daemon    /bin/sh
bin    /bin/sh
sys    /bin/sh
sync    /bin/sync
games    /bin/sh
man    /bin/sh
-------------------------------------------------------

BEGIN 和 END 块
通常,对于每个输入行,awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况,awk 允许您定义一个 BEGIN 块。我们在前一个示例中使用了 BEGIN 块。因为 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。
awk 还提供了另一个特殊块,叫作 END 块。awk 在处理了输入文件中的所有行之后执行这个块。通常,END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

mutian@mutian:~/soft/compile/test$ cat file 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
mutian@mutian:~/soft/compile/test$ awk -F : 'BEGIN{count=0;print "go"} {count++;print $7;} END{print "user count is " count}' file
go
/bin/bash
/bin/sh
/bin/sh
/bin/sh
/bin/sync
user count is 5

 

mutian@mutian:~/soft/compile/test$ cat file
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
mutian@mutian:~/soft/compile/test$ awk -F: '$5=="root"{print $1" "$2" "$5" "$6" "$7}' file
root x root /root /bin/bash
mutian@mutian:~/soft/compile/test$ grep root file |awk -F : '{print $1" "$2" "$5" "$6" "$7}'    #not suggested, not effective
root x root /root /bin/bash

 

posted @ 2014-11-28 10:49  牧 天  阅读(316)  评论(0)    收藏  举报