遇到个处理文本文件的问题
cat test.txt
"355356" "1700870" "1" "0202" ""
"355356" "1700871" "2" "" "02046"
"355356" "1700870" "" "2" "02046"
"1700870" "1700873" "" "1" "0202"
把第2列是1700870的数据改为1700888
起初我得想法是直接用sed,
sed -i "s,1700870,1700888,g" test.txt
得到数据如下,一开始我认为这种方法并无问题,可后来发现犯了很傻的错误。 第一列的最后一个字段也被替换了。
"355356" "1700888" "1" "0202" ""
"355356" "1700871" "2" "" "02046"
"355356" "1700888" "" "2" "02046"
"1700888" "1700873" "" "1" "0202"
后来用awk去解决这个问题
思路是对第二列等于1700870的行做处理
awk -F "\"" '{if ($4==1700870) $4=1700888}' test.txt
什么结果都没有打印,后来在网上搜了一下,想打印处理过的文本要么用print,要么在最后加个1,这里的1是个省略符,等价于 /.*/ 如下:
awk -F "\"" '{if ($4==1700870) $4=1700888}1' test.txt
结果如下
355356 1700888 1 0202
"355356" "1700871" "2" "" "02046"
355356 1700888 2 02046
"1700870" "1700873" "" "1" "0202"
不知道为什么引号没了,准定不符合规则,原因是在awk处理每一行数据的时候会把输出分隔符用默认的”空格“代替,所以我们发现每个
处理过的行都没了引号。
搜索了一下awk的用法,发现awk用法如下:
$0 表示整个当前行$1 每行第一个字段NF 字段数量变量NR 每行的记录号,多文件记录递增FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始\t 制表符\n 换行符FS BEGIN时定义分隔符RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)~ 匹配,与==相比不是精确比较!~ 不匹配,不精确比较== 等于,必须全部相等,精确比较!= 不等于,精确比较&& 逻辑与|| 逻辑或+ 匹配时表示1个或1个以上/[0-9][0-9]+/ 两个或两个以上数字/[0-9][0-9]*/ 一个或一个以上数字FILENAME 文件名OFS 输出字段分隔符, 默认也是空格,可以改为制表符等ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕-F'[:#/]' 定义三个分隔符
可以在输出时候自己指定输出分隔符OFS。
awk -F "\"" '{OFS="\""} {if ($4==1700870) $4=1700888}1' test.txt
结果如下符合需求:
"355356" "1700888" "1" "0202" ""
"355356" "1700871" "2" "" "02046"
"355356" "1700888" "" "2" "02046"
"1700870" "1700873" "" "1" "0202"
但上面的awk语法太难看,所以改进一下
awk 'BEGIN{FS=OFS="\""} {if ($4==1700870) $4=1700888}1' test.txt
把定义的输入和输出字符放到BEGIN里面,增强了程序的可读性。