在unix中使用sed替换一个单词的多次出现

在unix中使用sed替换一个单词的多次出现,unix,sed,Unix,Sed,在unix中,我需要用空格替换出现的word。 我的文件如下所示。我需要用一个空格来代替| NA | 文件格式 1234|NA|NA|abcd|xyz 2345|NA|NA|NA|lmn 456|NA|abcd|xya|ggh 预期产量 1234| | |abcd|xyz 2345| | | |lmn 456| |abcd|xya|ggh 我正在使用以下命令,但它只替换第一次出现的命令 sed 's/|NA|| |/g' 虽然g修饰符进行“全局”替换,但替换必须不重叠。当需要重叠替换时,必

在unix中,我需要用空格替换出现的word。 我的文件如下所示。我需要用一个空格来代替| NA |

文件格式

1234|NA|NA|abcd|xyz
2345|NA|NA|NA|lmn
456|NA|abcd|xya|ggh
预期产量

1234| | |abcd|xyz
2345| | | |lmn
456| |abcd|xya|ggh
我正在使用以下命令,但它只替换第一次出现的命令

sed 's/|NA|| |/g'

虽然
g
修饰符进行“全局”替换,但替换必须不重叠。当需要重叠替换时,必须循环:

$ sed ':a; s/|NA|/| |/g; ta' file.txt
1234| | |abcd|xyz
2345| | | |lmn
456| |abcd|xya|ggh
以上内容在GNU sed上进行了测试。对于BSD(OSX)sed(帽尖:Jonathan Leffler),标签
a
必须仅出现在命令字符串的末尾:

sed -e ':a' -e ' s/|NA|/| |/g; ta' file.txt
工作原理
  • :a
    创建标签
    a

  • s/| NA |/| | |/g
    执行所需的替换,但仅对
    |NA |
    的非重叠实例执行替换

  • ta
    告诉sed如果前面的替换命令导致行发生任何更改,则跳到标签
    a
    。这样,替换命令将根据需要重复多次,以替换每次出现的
    |NA


为了清晰、简单、可移植、可扩展等,只需使用awk即可:

$ awk '{while(gsub(/\|NA\|/,"| |"));}1' file
1234| | |abcd|xyz
2345| | | |lmn
456| |abcd|xya|ggh

在循环中,gsub()第一次替换regexp的所有奇数,第二次替换剩下的任何奇数。它将与任何UNIX系统上的任何awk一样工作。

试图跳出竖线完全失败。然后在没有人的情况下进行了一次尝试 有垂直杆参与,它的工作!还错过了 替换仅为一个空格,现已更正。这样一来,场地就很方便了 可通过添加空间进行扩展

 awk '{gsub(/NA/," ")}1' file 
1234| | |abcd|xyz
2345| | | |lmn
456| |abcd|xya|ggh

BSD
sed
不喜欢
:a
后面的分号。最简单的修复方法是
sed-e:a'-e的/| NA |/| |/g;ta'
,但如果
ta
后面跟着更多的命令,则需要在一个单独的
-e
参数中隔离额外的命令。@JonathanLeffler谢谢!使用BSD解决方案更新答案。感谢John1024和Jonathan Leffler。两种解决方案似乎都很有效。但是,我使用的是Linux,将使用John1024的解决方案。您显示的语法是语法错误。你可能的意思是:<代码> SED S//NA N//i'//'(中间有一个斜线,从你的中间丢失)。这应该会改变第二行中出现的第一个和第三个
NA
,但不会改变第二个。除了循环技术,您还可以简单地编写两次有效表达式;这也可以。@John1024是的,你说得对。修好了,谢谢。我以为我是在gawk下运行它的,但结果证明我使用的是OSX awk,我本不该相信它能用于测试的!尽管本准则可以回答这个问题,但提供关于为什么和/或如何回答这个问题的额外上下文将显著提高其长期价值。请在您的回答中添加一些解释。