I have a file which contains many lines(line delimiter is ~). Each line,I have many elements which is seperated by a delimiter '*'. What I want to do is , I will be having a line that starts with string TRN in my file. It can have 4(including TRN) or more data points in it. Something like,
我有一个包含许多行的文件(行分隔符是〜)。每一行,我有许多元素,用分隔符'*'分隔。我想要做的是,我将在我的文件中有一个以字符串TRN开头的行。它可以包含4个(包括TRN)或更多数据点。就像是,
TRN*1*S521000035*1020494919~
TRN*1*S521000035*1020494919*787989800~
I want to replace the fourth data point from this lines to abc123. ie,
我想将这行中的第四个数据点替换为abc123。即
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
I tried using sed command with regular expression
我尝试使用正则表达式的sed命令
sed -i 's/^TRN\*(.*)\*(.*)\*(.*)$/abc123/g' file.txt
But the whole string is getting replaced to abc123.
但是整个字符串都被替换为abc123。
Is it possible to change only its 4th datapoint using sed command ?
是否可以使用sed命令仅更改其第4个数据点?
5 个解决方案
#1
2
Using GNU sed:
使用GNU sed:
$ sed -r -i 's/^((\w+\*){3})\w*(.*)/\1abc123\3/g' file.txt
Output:
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
#2
2
sed is your friend.
sed是你的朋友。
Give a try to this tested version:
尝试这个测试版本:
$ sed "s/^\(TRN[*][^*][^*]*[*][^*][^*]*[*]\)[^*][^*]*\(.*~\)/\1abc123\2/" afile.txt
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
You might want to read the man pages to have more details on regexp and sed
您可能希望阅读手册页以获得有关regexp和sed的更多详细信息
#3
1
This might work for you (GNU sed):
这可能适合你(GNU sed):
sed 's/[^*~]\+/abc123/4' file
Replace the fourth occurrence of something which is does not contain a ~
or a *
with abc123
.
用abc123替换第四次出现的不包含〜或a *的内容。
#4
0
AWK should do the trick in a pretty concise and readable way. FS changes the field separator so that you can identify where you want it to break inside of a line.
AWK应该以非常简洁和可读的方式完成这个技巧。 FS会更改字段分隔符,以便您可以确定要在行内打破的位置。
$ awk 'BEGIN { FS="*|~" }{ sub($4, "abc123"); print $0}' file.txt
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
#5
0
While you can do this with sed it is much easier to achieve the desired effect with awk. The program awk is especially useful to analyse and transform tabular-structured data, as in your case:
虽然你可以使用sed来实现这一点,但使用awk实现所需的效果要容易得多。 awk程序对于分析和转换表格结构数据特别有用,如你的情况:
awk -F'*' -v OFS='*' '{$4 = "abc123"; print}'
This reads:
awk Run the program awk
-F'*' Use the * as a field delimiter on input
-v OFS='*' Use the * as a field delimiter on output
'{ On each record …
$4 = "abc123";
… set the 4th field to "abc123"
print
… and print the curent record
}'
It is also easy to expand on that example to selectively replace the 4-th field, depending on the value of the other fields.
根据其他字段的值,也可以很容易地扩展该示例以选择性地替换第4个字段。
#1
2
Using GNU sed:
使用GNU sed:
$ sed -r -i 's/^((\w+\*){3})\w*(.*)/\1abc123\3/g' file.txt
Output:
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
#2
2
sed is your friend.
sed是你的朋友。
Give a try to this tested version:
尝试这个测试版本:
$ sed "s/^\(TRN[*][^*][^*]*[*][^*][^*]*[*]\)[^*][^*]*\(.*~\)/\1abc123\2/" afile.txt
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
You might want to read the man pages to have more details on regexp and sed
您可能希望阅读手册页以获得有关regexp和sed的更多详细信息
#3
1
This might work for you (GNU sed):
这可能适合你(GNU sed):
sed 's/[^*~]\+/abc123/4' file
Replace the fourth occurrence of something which is does not contain a ~
or a *
with abc123
.
用abc123替换第四次出现的不包含〜或a *的内容。
#4
0
AWK should do the trick in a pretty concise and readable way. FS changes the field separator so that you can identify where you want it to break inside of a line.
AWK应该以非常简洁和可读的方式完成这个技巧。 FS会更改字段分隔符,以便您可以确定要在行内打破的位置。
$ awk 'BEGIN { FS="*|~" }{ sub($4, "abc123"); print $0}' file.txt
TRN*1*S521000035*abc123~
TRN*1*S521000035*abc123*787989800~
#5
0
While you can do this with sed it is much easier to achieve the desired effect with awk. The program awk is especially useful to analyse and transform tabular-structured data, as in your case:
虽然你可以使用sed来实现这一点,但使用awk实现所需的效果要容易得多。 awk程序对于分析和转换表格结构数据特别有用,如你的情况:
awk -F'*' -v OFS='*' '{$4 = "abc123"; print}'
This reads:
awk Run the program awk
-F'*' Use the * as a field delimiter on input
-v OFS='*' Use the * as a field delimiter on output
'{ On each record …
$4 = "abc123";
… set the 4th field to "abc123"
print
… and print the curent record
}'
It is also easy to expand on that example to selectively replace the 4-th field, depending on the value of the other fields.
根据其他字段的值,也可以很容易地扩展该示例以选择性地替换第4个字段。