我正在使用 sed 执行以下操作:
- 匹配模式(例如:以 开头的行
#
) - 替换匹配(例如:将
#
开头的字符替换为空/将其删除) - 打印到标准输出(例如:将结果替换打印到标准输出,因为我们正在使用
-i
) #
删除匹配(例如:删除行首包含字符的整行)
这是在文件上完成的,因此,sed
与标志一起使用时不会输出到标准输出-i
,除非我使用以下内容诡计:
sed -i -e 's/^\(#\)/\1/w /dev/stdout' -e '/^#/d' test
在名为 的文件上test
,包含以下示例内容:
#this
#is
a
test
以上适用于一切,除了替换...这里是实现替换的一个(我尝试在#
将字符打印到标准输出之前删除该字符):
sed -i -e 's/^\(#\)//w /dev/stdout' -e '/^#/d' test
这与上面类似,除了我替换\1
为//
所以它删除#
而不是打印整行......
问题是,最后一个不起作用删除行,而只是替换并打印。第一个确实适用于除替换之外的所有内容(例如:删除#
行开头的符号)
为什么这不起作用(第二次尝试,即第一次尝试有效,只是它不删除字符#
)?
答案1
第一个表达式删除了第二个表达式可能匹配的s/^\(#\)//w /dev/stdout
内容。/^#/d
你可以改为使用
sed -i -e '/^#/{s///w /dev/stdout' -e 'd}' test
前任。
$ cat test
#this
#is
a
test
$ sed -i -e '/^#/{s///w /dev/stdout' -e 'd}' test
this
is
$ cat test
a
test
答案2
和GNU awk
:
awk -i inplace '{if (/^#/) {sub(/^#/, "");arr[++i]=$0;} else print}END{for (a in arr) print arr[a]}' input
选项-i
或--include
用于包含awk
源库inplace
。
inplace 扩展模拟 GNU sed 的
-i
选项,该选项对每个输入文件执行“就地”编辑。
if (/^#/)
这会查看是否有以 开头的行#
。如果找到则sub()
替换#
为空字符串。现在进行替换并创建$0
一个数组。arr
该数组是按END
块打印的,因此会打印在屏幕上。正在打印的其他行(在main
块中)通过 发送到文件inplace
。
$ awk -i inplace '{if (/^#/) {sub(/^#/, "");arr[++i]=$0;} else print}END{for (a in arr) print arr[a]}' input
this
is
$ cat input
a
test