美文网首页
初写shell 时遇到的一些问题

初写shell 时遇到的一些问题

作者: wind_sky | 来源:发表于2019-08-08 14:31 被阅读0次

    一. 逐行处理文本

    1.通过read命令完成.

    read命令接收标准输入,或其他文件描述符的输入,得到输入后,read命令将数据放入一个标准变量中。

    利用read读取文件时,每次调用read命令都会读取文件中的"一行"文本。

    当文件没有可读的行时,read命令将以非零状态退出。

    cat data.dat | while read line;do
      echo "File:${line}" 
    done
    while read line;do 
      echo "File:${line}" 
    done < data.dat
    

    2.使用awk命令完成

    awk是一种优良的文本处理工具,提供了极其强大的功能.

    利用awk读取文件中的每行数据,并且可以对每行数据做一些处理,还可以单独处理每行数据里的每列数据.

    cat data.dat | awk '{print $0}'
    cat data.dat | awk 'for(i=2;i<NF;i++) {printf $i} printf "\n"}'
    

    第1行代码输出data.dat里的每行数据,第2代码输出每行中从第2列之后的数据.

    如果是单纯的数据或文本文件的按行读取和显示的话,使用awk命令比较方便.

    3.使用for var in file 命令完成

    for var in file 表示变量var在file中循环取值.取值的分隔符由$IFS确定.

    for line in $(cat data.dat);do
      echo "File:${line}"
    done
    # 或
    for line in `cat data.dat`;do
      echo "File:${line}"
    done
    

    如果输入文本每行中没有空格,则 line 在输入文本中按换行符分隔符循环取值。如果输入文本中包括空格或制表符,则不是换行读取,line 在输入文本中按空格分隔符或制表符或换行符特环取值,可以通过把 IFS 设置为换行符来达到逐行读取的功能。

    IFS的默认值为:空白(包括:空格,制表符,换行符).

    注意:
    这段代码

    path_all=""
    cat test.txt | while read line
    do
        path_all="${path_all} ${line}"
    done
    echo $path_all
    

    这段代码的本意是将test 文件中的文本按行读出并拼接成一行,但最后的输出却是空串,出现这种问题的原因和while 有关,
    while循环读取文件中内容有两种写法,一种是管道符,一种是重定向,写法如下

    管道符:

    cat $file_name | while read line
    do
      #deal with line
    done
    

    重定向:

    while read line
    do
      #deal with line
    done < $file_name
    

    这两种做法的区别在于,重定向是内建命令,而管道符是非内建命令,之所以我写的脚本出现了输出是空的问题,原因就在这里,linux执行shell时,会创建“子shell”运行shell中的命令,当运行到非内建指令时,会创建“孙shell”运行非内建指令,变量的作用于在每个shell中有效,所以,非内建指令中定义的这些变量就只能在孙shell运行,而在子shell中不生效,所以,即便在while中给path_all赋值了,子shell中也不会获取到这个值。

    解决这个问题的办法有两种,如果不是必须使用管道符的方式写while循环,可以用重定向的写法,这种写法循环内的变量在子shell中是生效的,比较简便;如果非要使用管道符的方式,可以创建临时文件,用于存放孙shell中的输出。

    二. 字符串截取

    假设有变量 var=http://www.aaa.com/123.htm.

    1. # 号截取,删除左边字符,保留右边字符。 (非贪婪匹配)

    echo ${var#*/}
    

    其中 var 是变量名,# 号是运算符,*/ 表示从左边开始删除第一个 / 号及左边的所有字符
    即删除 http://
    结果是 :www.aaa.com/123.htm

    2. ## 号截取,删除左边字符,保留右边字符。(贪婪匹配)

    echo ${var##*/}
    

    ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符
    即删除 http://www.aaa.com/

    结果是 123.htm

    3. %号截取,删除右边字符,保留左边字符 (非贪婪匹配)

    echo ${var%/*}
    

    %/* 表示从右边开始,删除第一个 / 号及右边的字符

    结果是:http://www.aaa.com

    4. %% 号截取,删除右边字符,保留左边字符 (贪婪匹配)

    echo ${var%%/*}
    

    %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符
    结果是:http:

    5. 从左边第几个字符开始,及字符的个数

    echo ${var:0:5}
    

    其中的 0 表示左边第一个字符开始,5 表示字符的总个数。
    结果是:http:

    6. 从左边第几个字符开始,一直到结束。

    echo ${var:7}
    

    其中的 7 表示左边第8个字符开始,一直到结束。
    结果是 :www.aaa.com/123.htm

    7. 从右边第几个字符开始,及字符的个数

    echo ${var:0-7:3}
    

    其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。
    结果是:123

    8. 从右边第几个字符开始,一直到结束。

    echo ${var:0-7}
    

    表示从右边第七个字符开始,一直到结束。
    结果是:123.htm

    注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

    9. 字符串分割

    大多数语言中都有类似string.split('sp') 的方法将字符串按照某个字符或子串切分成一个数组,shell 中可以如下

    str="hello,world,i,like,you,babalala"
    arr=(${str//,/ })
    

    将str按照','切分成一个数组,并遍历之。当然,这里分隔符可以是一个子串。

    三. 数组的操作

    1. 定义数组

    declare -a array              # 显示声明了数组array
    delcare -a array[10]          # 数组大小没有上限,所以定义时指定的大小会被忽略
    array[key]=value              # array[0]=one,array[1]=two
    array=(value1 value2...)   # value的形式都是[subscript]=string,下标和等号可以省略,示例如下。
    array=(value1 value2 value3) # array[0]=value1,array[1]=value2,array[2]=value3
    array=([0]=value1 [2]=value3 [3]=value)
    

    2. 访问数组

    数组的任何元素都可以用 ${array[subscript]} 来引用,花括号是必须的,以避免和路径扩展冲突。 如果 subscript 是@或是*,它扩展为array的所有成员。这两种下标只有在双引号中才不同。在双引号中,${name[*]} 扩展为一个词,由所有数组成员的值组成,用特殊变量IFS的第一个字符分隔数组成员;${array[@]} 将array 的每个成员扩展为一个词。 如果数组没有成员,${name[@]} 扩展为空串。

    3. 其他更多

    请见https://www.thegeekstuff.com/2010/06/bash-array-tutorial/

    四. 变量

    1. 作用域
    http://c.biancheng.net/view/773.html

    2. 比较
    https://blog.csdn.net/u010622613/article/details/80706119

    相关文章

      网友评论

          本文标题:初写shell 时遇到的一些问题

          本文链接:https://www.haomeiwen.com/subject/lirxjctx.html