如果我有一个包含柱状条目的文件,是否可以仅替换特定列中的特定条目并将更改保存到同一文件?
文件示例abc.txt
:
SR|FRUITS|COLOR|
1|Apple|Red|
2|Mango|Yellow|
3|Orange|Orange|
4|W.Melon|Green|
需要改变橙子从水果到橙色_编辑。然而,颜色中的橙色不应受到影响。
答案1
awk
你可以用类似的两步来完成
awk '{$2="VAL";print}' input_file > temp_file
mv temp_file input_file
这将在空白处分割输入文件,替换第二列中的值(对于不同的列使用 2 以外的任何其他数字),因此它现在将是“VAL”。除非你用OFS
输出字段分隔符来改变它,否则它将是一个空格。如果您想要其他内容,可以在引号内添加类似 'BEGIN {OFS="\t"}...' 的内容,以将输出字段分隔符设置为您想要的任何内容。
如果您希望这些值不是常量,您将需要做更多的工作,但您可以调整它来做到这一点。
要使此功能适用于您的情况的编辑,您可以执行以下操作:
awk -F\| 'BEGIN {OFS="|";} $2~/^Orange$/ {$2="Orange_edit";} {print}' abc.txt > temp_file
mv temp_file abc.txt
这首先告诉根据传递awk
来分割字段。然后,我们通过制作第一个代码块(匹配 BEGIN 的部分,匹配执行开始的关键字)并设置我们的, 或输出字段分隔符,将输出设置为也用于输出分隔符(默认为空格) 。正如 Otheus 指出的,我们可以将输出分隔符设置为与输入分隔符相同。|
-F\|
|
awk
OFS
{OFS=FS}
之后我们开始查看线路。我们比较由 引用的第二个字段$2
,然后使用 来检查它是否与正则表达式匹配~
。之后~
是我们要匹配的正则表达式,^
这里表示匹配字段的开头,然后我们有字符串“Orange”,然后$
它匹配字段的结尾。由于这是一个硬编码字符串,Otheus 也正确地观察到,我们可以只在这里测试字符串是否相等,然后执行$2=="Orange"
并跳过正则表达式处理,因为这次它实际上没有执行任何操作。如果匹配成功,{}
则执行后的代码块会将新值保存到第二个字段中。
最后,我们为每一行执行最后一个代码块{print}
,但是当上面的“Orange”匹配成功时,我们更改了第二个字段的值,因此它会使用新值而不是旧值进行打印。
awk
通常会打印到屏幕上(显然较新的版本gawk
有一个选项可以简化这部分),因此我们将其保存到一个文件中,然后将该文件移回到原始名称。
答案2
有很多方法可以做到这一点。最简单的可能是awk
和perl
:
GNU
gawk
。如果您安装了相对较新的版本gawk
,您可以像这样进行内联编辑:gawk -i inplace -F"|" -vOFS="|" '$2=="Orange"{$2="Orange_Edit"}1;' file
指示
-i inplace
就地gawk
编辑文件,设置-F"|"
字段分隔符|
,并-vOFS="|"
设置输出字段分隔符|
。仅当第二个字段为 时,脚本才将第二个字段 ($2
)设置为。这是“打印当前行”的简写。Orange_Edit
Orange
1;
awk
Perl
perl -i -F"\|" -lane '$F[1]="Orange_Edit" if $F[1] eq "Orange"; print join "|",@F' file
这
-a
使得 Perl 的行为类似于awk
对 给定的值进行分割线-F
,将结果字段保存在@F
数组中。然后,脚本将第二个字段($F[1]
,数组从 0 开始)设置为 ,Orange_Edit
如果其原始值为Orange
。然后,将这些字段连接|
并打印。如果您只想更改第一次出现的
Orange
,您可以简化并使用sed -i 's/Orange/Orange_Edit/' file
您可以通过仅匹配整个字段来使其更加健壮:
sed -i 's/|Orange|/|Orange_Edit|/' file
答案3
您可以使用perl
:
$ perl -i.bak -F'\|' -aple 's/Orange/Orange_Edit/ if $F[1] eq "Orange"' file
或更安全的版本:
$ perl -i.bak -F'\|' -aple '$F[1]=~s/^Orange$/Orange_Edit/; $_=join "|",@F' file