作者:朱玉龙1977 | 来源:互联网 | 2022-12-07 14:44
我不确定这是否可以在sed(或awk或任何bash工具)中执行我想要的操作:
我想创建一个脚本替换: )
字符串by
和) :
by
.这可以通过sed轻松完成:
echo "test : )" | sed 's/: )//g'
echo "test ) :" | sed 's/) ://g'
不幸的是,有时我会有这样的字符串:
I'm happy : ) : ) : )
I'm sad ) : ) : ) :
在这种情况下,输出应该是:
I'm happy
I'm sad
但通过结合上面的两个命令:
echo "I'm happy : ) : ) : )" | sed 's/: )//g' | sed 's/) ://g'
echo "I'm sad ) : ) : ) :" | sed 's/: )//g' | sed 's/) ://g'
我会得到:
I'm happy
I'm sad ) :
解决这个问题的方法是通过从左到右处理字符串来并行地进行两个替换.我尝试使用这样的东西:sed 's/a/b/g;s/c/d/g'
但是替换只是一个接一个地完成,并没有解决问题.
1> Ed Morton..:
使用GNU awk为第3个arg匹配():
$ cat script1.awk
BEGIN {
map[": )"] = ""
map[") :"] = ""
}
{
while ( match($0,/(.*)(: \)|\) :)(.*)/,a) ) {
$0 = a[1] map[a[2]] a[3]
}
print
}
$ awk -f script1.awk file
I'm happy
I'm sad
有任何awk:
$ cat script2.awk
BEGIN {
map[": )"] = ""
map[") :"] = ""
}
{
while ( match($0,/: \)|\) :/) ) {
$0 = substr($0,1,RSTART-1) map[substr($0,RSTART,RLENGTH)] substr($0,RSTART+RLENGTH)
}
print
}
$ awk -f script2.awk file
I'm happy
I'm sad
虽然在这种情况下两种方法都产生相同的输出,但第一种方法实际上是从字符串的末尾到前导的礼貌,.*
而第二种方法从前到后工作.您可以通过此测试看到:
$ echo ': ) :' | awk -f script1.awk
:
$ echo ': ) :' | awk -f script2.awk
:
你可以用任何带有调整功能的awk做一个从前到后的传递,但我不认为这是你真正想要的.
编辑以从地图构建正则表达式:
$ cat tst.awk
BEGIN {
map[": )"] = ""
map[") :"] = ""
for (emoji in map) {
gsub(/[^^]/,"[&]",emoji)
gsub(/\^/,"\\^",emoji)
emojis = (emojis == "" ? "" : emojis "|") emoji
}
}
{
while ( match($0,emojis) ) {
$0 = substr($0,1,RSTART-1) map[substr($0,RSTART,RLENGTH)] substr($0,RSTART+RLENGTH)
}
print
}
$ awk -f tst.awk file
I'm happy
I'm sad
当然,我刚刚添加了一个版本.