[toc]
[TOC]
特殊字符反斜杠的问题
#sed -i '4 s/^/good baby\n/' test.txt
执行成功,符合预期,但是
#sed -i '4 s/^/<center>查询结果:6个 <a href="./">继续</a>/' test.txt
却运行失败,经多次尝试排查,终于发现原因。
因为正则表达式中有'/'
这个特殊字符,应该进行转义。
改成'\/'
即可,但是实际在C代码中,采用system(cmd)
的方式,并未成功
由于时间紧张,未能深入排查。
但是在排查的时候,意外发现把's'
换成‘a’
,即进行追加而不是替换的话,可以完美工作。
不需要考虑特殊字符的转义问题,在'a'
后面,反斜杠'/'
成了普通字符。
#sed -i '8 a<center>查询结果:6个 <a href="./">继续</a>' test.txt
一个常用技巧,查询数据类型在哪个头文件中定义
grep -rn keyWords ../../ | sed -n "/\.h:\w\+/"p
find ../ -name '*.c' | xargs grep -rni keyWords
--->>输出中带有路径
find ../ -type f | grep '\.c' | xargs grep -rni keyWords
-->>这种情况下,输出带有路径,行数,内容
find ../ -name '*.c' | xargs -i grep -rni keyWords {}
==>>这种情况下,输出结果中,没有文件名
grep 执行条目过多时,会报错
# grep -rni keyWords `find ../../ -name *.c`
找到关键字所在的行,将其替换为别的内容
如:void function(int a, int b) 修改为:
static void function(int a, int b)
fileName=/home/user/a.c
lineNum=`sed -n '/void function/=' a.c` ; \
echo ${lineNum}; \
sed -i "${lineNum}d" a.c; \
sed -i "${lineNum}iStatic void function(int a, int b)" a.c
说明: sed -i "${lineNum}d" 删除指定行
sed -i "${lineNum}iXXX" 在指定行插入XXX
sed -n "/key/=" 查找关键字所在行,如果是多个,
则返回 3 5 7 这样的字符串,可以用数组接收
找到关键字,并在其后追加一行
第一步,制作准备原始文件
# cat pps
aaaa
bbbb
cccc
dddd
第二步,命令行实验,尝试先查找"cccc"所在的行,并在其后追加"zzzz"
# sed -e "/cccc azzzz"
aaaa
bbbb
cccc
zzzz
dddd
第三步,因为第二步实验成功,将其写入文件
# sed -i "/cccc azzzz" pps
# cat pps
aaaa
bbbb
cccc
zzzz
dddd
一个高难度应用
1、问题描述
源文本如下:
<test> blah blah blah blah blah widget blah blah blah
</test>
<formula> blah <details> widget </details>
</formula>
希望从文本中,提取出如下内容:
<test>widget</test>
<formula>widget</formula>
2、实现脚本
sed -ne '/[Ww][Ii][Dd][Gg][Ee][Tt]/,/^<\// {//p}' file.txt | awk 'NR%2==1 { sub(/^[ \t]+/, ""); search = $0 }
效果:
<test>widget</test>
<formula>widget</formula>
3、脚本讲解
## The sed pipe:
sed -ne '/[Ww][Ii][Dd][Gg][Ee][Tt]/,/^<\// {//p}'
## This finds the widget pattern, ignoring case, then finds the last,
## highest level markup tag (these must match the start of the line)
## Ultimately, this prints two lines for each pattern match
## Now the awk pipe:
NR%2==1 { sub(/^[ \t]+/, ""); search = $0 }
## This takes the first line (the widget pattern) and removes leading
## whitespace, saving the pattern in 'search'
NR%2==0 { end = $0; sub(/^<\//, "<"); printf "%s%s%s\n", $0, search, end }
## This finds the next line (which is even), and stores the markup tag in 'end'
## We then remove the slash from this tag and print it, the widget pattern, and
## the saved markup tag
对包含特殊关键字的行进行操作
1、在包含关键字的行中,删除另外一个关键字
# cat ass.txt
good boy
good man
good girl
# 将包含 man 的行中,对应的关键字 good 删除
# sed -i /man/{s/good//} ass.txt
# cat ass.txt
good boy
man
good girl
2、将同时包含关键字A和关键字B的行删除
# cat ass.txt
good boy
good man
good girl
# 将包含 man 的行中,对应的关键字 good 删除
# sed -i /man/{/good/d} ass.txt
# cat ass.txt
good boy
good girl
sed 的一个大 bug
1、诡异现象
写入文件,出现故障。
一段脚本之中,前面写入表现都很正常。
但是执行到某一段代码时,出现莫名其妙的故障,代码如下:
#==>>这是前面一段代码,表现正常,能成功写入,符合预期
for fileName in ${file_1} ${file_2}
do
lineNum=`sed -n /keyword_1/= ${fileName}`
startLine=$((lineNum - 5))
endLine=$((lineNum + 2))
# 删除这一段内容
sed -i "${startLine},${endLine} d"
# 下面用 sed 重新插入代码
sed -i "${startLine}a #ifndef OK" ${fileName} ; startLine=$((${startLine} + 1))
sleep 0.01 # 为了防止写文件太耗时,加一个延时10ms
sed -i "${startLine}a #define OK 0" ${fileName} ; startLine=$((${startLine} + 1))
sleep 0.01 # 为了防止写文件太耗时,加一个延时10ms
sed -i "${startLine}a #define ERRPR 1" ${fileName} ; startLine=$((${startLine} + 1))
sleep 0.01 # 为了防止写文件太耗时,加一个延时10ms
...
sed -i "${startLine}a #endif" ${fileName} ; startLine=$((${startLine} + 1))
done
#==>>第二段代码,与第一段雷同,只是行数略多,20行而已,但是后来发现跟行数无关
for fileName in ${file_3} ${file_4}
do
lineNum=`sed -n /keyword_2/= ${fileName}`
startLine=$((lineNum - 19))
endLine=$((lineNum + 2))
# 删除这一段内容
sed -i "${startLine},${endLine} d"
# 下面用 sed 重新插入代码
sed -i "${startLine}a #ifndef OK" ${fileName} ; startLine=$((${startLine} + 1))
sleep 0.01 # 为了防止写文件太耗时,加一个延时10ms
sed -i "${startLine}a #define OK 0" ${fileName} ; startLine=$((${startLine} + 1))
sleep 0.01 # 为了防止写文件太耗时,加一个延时10ms
sed -i "${startLine}a #define ERRPR 1" ${fileName} ; startLine=$((${startLine} + 1))
sleep 0.01 # 为了防止写文件太耗时,加一个延时10ms
...
sed -i "${startLine}a #endif" ${fileName} ; startLine=$((${startLine} + 1))
done
# 此时,执行到第二段代码时,实际上成了死循环。如果只有一两行写入语句
# 还能跳出死循环,但目标文件已被写乱掉
# 如果行数多,直接就是死循环,及时中止,txt 文件已经达到37M
# 此问题百思不得其解,实在诡异
2、发现一点不同
在出故障的代码段中,发现最后一行行为正常:
sed -i "${startLine}a #endif" ${fileName} ; startLine=$((${startLine} + 1))
它能正常写入,然后用它替换其它的行:
sed -i "${startLine}a #ifndef OK" ${fileName} ; startLine=$((${startLine} + 1))
改为 `#endif`之后,就能正常写入,其它字符串就不行,将中间空格去掉也不行:
sed -i "${startLine}a #ifndefOK" ${fileName} ; startLine=$((${startLine} + 1))
到了这份上,其实不就是写一个普通字符串吗,`#ifndefOK` 和 `#endif`能有啥区别?