Bash 如何使用sed修改具有管道分隔值的文件中特定列中的值
我有一个以下格式的文件:Bash 如何使用sed修改具有管道分隔值的文件中特定列中的值,bash,shell,sed,Bash,Shell,Sed,我有一个以下格式的文件: #id|firstName|lastName|gender|birthday|creationDate|locationIP|browserUsed 933|Mahinda|Perera|male|19891203|2010-03-17T13:32:10.447+0000|192.248.2.123|Firefox 如您所见,分隔符是“|”,第五个字段是“生日””。我想使用sed将“-”放在8位数字之间,以便得到如下结果: 1989-12-03 我的尝试是:sed的/
#id|firstName|lastName|gender|birthday|creationDate|locationIP|browserUsed
933|Mahinda|Perera|male|19891203|2010-03-17T13:32:10.447+0000|192.248.2.123|Firefox
如您所见,分隔符是“|”
,第五个字段是“生日”
”。我想使用sed将“-”
放在8位数字之间,以便得到如下结果:
1989-12-03
我的尝试是:sed的/…/&-/;s/:$/'| sed's/……/&-/;s/:$/'
但是这个命令会在我的文件的每一行的开头进行更改。我只想在第五个字段中进行更改。sed有可能吗
请注意,这是一个家庭作业
非常感谢。原创
$ cat data
#id|firstName|lastName|gender|birthday|creationDate|locationIP|browserUsed
933|Mahinda|Perera|male|19891203|2010-03-17T13:32:10.447+0000|192.248.2.123|Firefox
转变
$ cat data | sed -r 's/^(([^|]+\|){4})([0-9]{4})([0-9]{2})([0-9]{2})(.+)$/\1\3-\4-\5\6/'
#id|firstName|lastName|gender|birthday|creationDate|locationIP|browserUsed
933|Mahinda|Perera|male|1989-12-03|2010-03-17T13:32:10.447+0000|192.248.2.123|Firefox
这里有一些上下文帮助您理解
^ # Start of Line
(([^\|]+\|){4}) # Grab the first 4 fields in \1 (note \2 is not useful for us here)
([0-9]{4})([0-9]{2})([0-9]{2}) # Split up the field we want to modify in \3, \4 and \5
(.+) # Grab whatever is left in \6
$ # End of Line
虽然使用sed当然可以实现您想要的,但使用awk几乎肯定会更好。使用BSD awk、gawk和mawk对以下各项进行了测试:
awk -F'|' '
BEGIN {OFS=FS}
NF==1 {print; next}
{sub(/^....../, "&-", $5);
sub(/^..../, "&-", $5);
print;
} '
对于第5列中的意外值,您可能希望使上述内容更加可靠
如果确实需要使用sed,一种方法是使用[^ |]*
;例如,如果sed支持扩展正则表达式:
sed -r 's/^(([^|]*\|){4})(....)(..)(..)/\1\3-\4-\5/'
请注意,此处未使用\2
(在Mac上,使用
-E
而不是-r
)您不必转义字符类中的内容:[^\|]
也排除反斜杠,因为它们在这里并不特殊;您可能希望改为[^ |]
。这是因为我在更正命令时没有更正输出。现在更正。(已删除\2)您能告诉我为什么第四个字段打印两次吗?请使用:\1\3-\4-\5\6而不是\1\2\3-\4-\5\6(\2与集合中的最后一个字段匹配)。。我在发布正则表达式后立即更新了它。我想您可能会有第一个带有“\2”chksdsk的版本-似乎您误解了@Benjamin W.的评论,因此我建议您重新阅读,并进行相应调整。由于我使用管道,请您将其写在一行中好吗?管道可以分布在多行中,正如我所做的那样。不过,多亏了awk的慷慨,您可以将上面的多行程序压缩到一行,它就会工作。顺便说一下,要知道“sed-r”不是通用的;e、 你可以在Mac电脑上写“sed-e”,这很有帮助。非常感谢。