Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何使用sed修改具有管道分隔值的文件中特定列中的值_Bash_Shell_Sed - Fatal编程技术网

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”,这很有帮助。非常感谢。