Regex 如何仅替换文件中的特定列?

Regex 如何仅替换文件中的特定列?,regex,bash,sed,Regex,Bash,Sed,我正在使用一个名为test的长文件,该文件如下所示: AHAP USA|NIS00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR KJJLIL123124%|NIS00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR ASFASS9992|NIS00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY 我需要将字符串“NIS”替换为“NIX”,但是我只需要在由管道字符分隔的

我正在使用一个名为test的长文件,该文件如下所示:

AHAP   USA|NIS00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR
KJJLIL123124%|NIS00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR
ASFASS9992|NIS00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY
我需要将字符串“NIS”替换为“NIX”,但是我只需要在由管道字符分隔的第二列中实现这一点,我的数据的分隔符是管道“|”,我有几列,总共七列,我只想在第二列中进行替换

我试过:

$ sed s/NIS/NIX/g test
AHAP   USA|NIX00333|+NULL|NIXGOOGLE|NIX00005|*binary|NIXCAR
KJJLIL123124%|NIX00160|+NULL|NIXFACEBOOK|NIX00006|*binary|NIXBUR
ASFASS9992|NIX00164|+NULL|NIXTABLE|NIX00008|*binary|NIXFANCY
但它会影响与字符串匹配的所有列:NIS并将其更改为NIX,我只想影响第二列,我希望的输出是:

AHAP   USA|NIX00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR
KJJLIL123124%|NIX00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR
ASFASS9992|NIX00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY

我非常感谢您在这个问题上提供的帮助,谢谢您的帮助。

如果您遇到了列问题,请务必使用
awk
对其进行更好的本机控制:

$ awk 'BEGIN {FS=OFS="|"}{gsub("NIS","NIX",$2)}1' file
AHAP   USA|NIX00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR
KJJLIL123124%|NIX00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR
ASFASS9992|NIX00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY
这将对基于第二个
|
的字段执行替换。完成此替换后,
1
触发
awk
的默认操作,包括打印
$0
,该操作保存完整(更新)记录。

sed解决方案:

$ sed 's/^\([^|]*|[^|]*\)NIS/\1NIX/' infile 
AHAP   USA|NIX00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR
KJJLIL123124%|NIX00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR
ASFASS9992|NIX00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY
正则表达式,拆分:

^          # Start of line anchor
\(         # Start of capture gruop
    [^|]*  # Characters other than pipe - first column
    |      # Column separator between first and second column
    [^|]*  # Characters other than pipe - first part of second column
\)         # End of capture group
NIS        # What we actually want to replace
这有一个限制,因为它只替换第二列中第一次出现的
NIS
。示例输入没有更多内容,但如果有,我们可以使用条件分支重复替换,只要它更改模式空间:

sed '
:a
s/^\([^|]*|[^|]*\)NIS/\1NIX/
ta' infile
:a
是要跳转到的标签,
ta
是条件分支命令(“跳转到
:a
,如果替换做了什么”)

作为一个班轮:

sed ':a;s/^\([^|]*|[^|]*\)NIS/\1NIX/;ta' infile
BSD sed(正如在Mac OS中发现的)会抱怨标签后面没有换行符,所以我们可以根据需要重写

sed -e ':a' -e 's/^\([^|]*|[^|]*\)NIS/\1NIX/;ta' infile

谢谢,我真的很感激这个建议,我会考虑使用AWK而不是SED来处理列,只需要再问一个问题,那就是代替AWK的替代,我的意思是,如果你使用SED,你可以使用SED- I来改变同一个文件中的变化,你知道什么是awk的等价物吗?@neo33你可以使用GNU awk 4.1.0中的
-i inplace
。否则,诀窍总是
awk'…'文件>tmp_文件和&mv tmp_文件
。所有这些都在中进行了描述。是的,我看到了,非常感谢您的支持,这真的很有帮助。哇,这真的很有帮助。我的第一种方法是在sed中思考,但是这是使用正则表达式的一种很好的方法,尽管对于这个特定任务,使用awk稍微容易一点,我的意思是处理列,@neo33在Ed出现之前,让我自己说一下:在99.9%的情况下,awk比sed更快、更强大、更简洁。有人说,sed应该被忽略,因为它已经被awk取代了——有些人(像我一样)出于怀旧的原因喜欢涉足其中;)是的,我理解,可能是因为sed比awk更受欢迎,但是了解更多关于awk的信息肯定是一个非常好的主意,谢谢你的建议,我感谢你的支持。