使用 sed,如何替换给定文件每一行中倒数第 N 个出现的字符?
在这种情况下,我想将倒数第三个替换;
为,
输入
1;2;3;4;5;6;7;8;9
10;20;30;40;50;60;70;80;90
100;200;300;400;500;600;700;800;900
预期产出
1;2;3;4;5;6,7;8;9
10;20;30;40;50;60,70;80;90
100;200;300;400;500;600,700;800;900
我知道我可以像这样替换第六次出现
sed 's/;/,/6' input_file.csv > output_file.csv
或者最后一张
sed -r 's/(.*);/\1,/' input_file.csv > output_file.csv
但在我的具体情况下,由于一些细微差别,我需要从最后开始。
我尝试过类似的东西
sed -r 's/(.*);/\1,/3' input_file.csv > output_file.csv
答案1
您可以简单地反转这些行,更改第 N 个出现的位置,然后重新反转:
rev file | sed 's/;/,/3' | rev
答案2
您可以显式捕获另外两个分隔字段:
$ sed -r 's/(.*);([^;]*;[^;]*;)/\1,\2/' input_file.csv
1;2;3;4;5;6,7;8;9
10;20;30;40;50;60,70;80;90
100;200;300;400;500;600,700;800;900
或者更多地以编程方式
$ sed -r 's/(.*);(([^;]*;){2})/\1,\2/' input_file.csv
1;2;3;4;5;6,7;8;9
10;20;30;40;50;60,70;80;90
100;200;300;400;500;600,700;800;900
其中量词中的数字{n-1}
替换倒数第 n 个。
答案3
使用gawk
:
awk -F';' '{print gensub(";", ",", NF-3)}'
内置gawk
函数gensub()
用逗号替换倒数第 n 个分号。
答案4
我们GNU sed
可以这样做。
- 跳过任何进一步的处理,打印行,如果一行中少于 3 个分号,则返回读取下一行。
- 将所有分号更改为换行符。
- 逐步一一恢复换行符,直到剩下 3 个换行符。
- 现在将第一行更改为逗号,其余部分恢复。
sed -e '
s/;/&/3;T
y/;/\n/
:a;s/\n/&/4;tb
s//,/;y/\n/;/
:b;s//;/;ta
' file
1;2;3;4;5;6,7;8;9
10;20;30;40;50;60,70;80;90
100;200;300;400;500;600,700;800;900
我们Perl
进行分割并将字段分隔符记录在分割数组中(@F)。然后倒数第 6 个字段是倒数第三个分号,我们将其更改为逗号。休息不变。
perl -aF'(;)' -plse '
$F[-6]=",",s/.*/@F/ if @F >= 6;
' -- -\"= ./file
使用 POSIX awk,我们根据分隔符的位置修改分隔符:
awk -F\; -v n=3 '{ for(i=1; i<=NF; i++) printf "%s%s", $i, (i==NF-n?",":(i==NF?ORS:FS)) }' infile