替换每行中倒数第 n 个出现的字符串

替换每行中倒数第 n 个出现的字符串

使用 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

相关内容