替换每行中第 n 个从结尾出现的字符串

Mat*_*epa 9 debian sed text-processing

使用 sed,如何在给定文件的每一行中替换第 N 个到最后一个字符?

在这种情况下,我想更换3到最后;,

输入

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
Run Code Online (Sandbox Code Playgroud)

预期产出

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
Run Code Online (Sandbox Code Playgroud)

我知道我可以像这样替换第 6 次出现

sed 's/;/,/6' input_file.csv > output_file.csv
Run Code Online (Sandbox Code Playgroud)

或者最后一个

sed -r 's/(.*);/\1,/' input_file.csv > output_file.csv
Run Code Online (Sandbox Code Playgroud)

但在我的特殊情况下,由于一些细微差别,我需要从最后开始。

我试过类似的东西

sed -r 's/(.*);/\1,/3' input_file.csv > output_file.csv
Run Code Online (Sandbox Code Playgroud)

Fel*_*xJN 13

您可以简单地反转线条,更改第 N 个出现,然后重新反转:

 rev file | sed 's/;/,/3' | rev
Run Code Online (Sandbox Code Playgroud)


ste*_*ver 12

您可以明确捕获另外两个分隔字段:

$ 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
Run Code Online (Sandbox Code Playgroud)

或者更多地以编程方式

$ 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
Run Code Online (Sandbox Code Playgroud)

其中量词中的数字{n-1}替换倒数第 n 个。


Pra*_*ngh 8

使用gawk

awk -F';' '{print gensub(";", ",", NF-3)}'
Run Code Online (Sandbox Code Playgroud)

gawk内置功能gensub()内容替换第n用逗号最后分号。


cas*_*cas 6

sed好当你与整个线工作,但awkperl是更好,当你需要使用的字段/列工作线之内。

$ perl -F';' -lane 'splice @F,-4,2,join(",",@F[-4..-3]); print join(";",@F)' input.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
Run Code Online (Sandbox Code Playgroud)

这会将行拆分为 @F 数组,;用作分隔符。然后,它将倒数第四个和倒数第三个字段替换为一个字符串,该字符串包含两个字段的值,以逗号分隔。

然后它用分号作为字段分隔符打印整个@F 数组。


splice是 perl 内置的通用数组操作函数。有几种形式可以使用它,但我在这里使用的形式是:

splice ARRAY,OFFSET,LENGTH,LIST
Run Code Online (Sandbox Code Playgroud)

IE

splice @F, -4, 2, join(",",@F[-4..-3])
Run Code Online (Sandbox Code Playgroud)
  • ARRAY:@F,perl 与-For-a选项一起使用时的默认数组,类似于 awk 的 $1, $2, $3 字段编号。
  • OFFSET:-4,倒数第四个字段
  • LENGTH: 2、两个字段(即$F[-4]$F[-3]
  • LIST:在这种情况下,“LIST”只有一个元素,一个包含字段 -4 和 -3 的值的字符串,由逗号连接。不过,一般而言,LIST 可以是任意长度的数组,因此splice也可用于向数组中插入更多字段。

详情请参阅perldoc -f splice

此外,@F[-4..-3]在 perl 中称为数组切片。范围运算符..返回字段 -4-3的元素。对于这个脚本,它也可以写成@F[-4,-3],即元素 -4-3。可以使用范围和/或列表指定数组切片。