初写shell 时遇到的一些问题

2019-08-08  本文已影响0人  wind_sky

一. 逐行处理文本

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

上一篇下一篇

猜你喜欢

热点阅读