bash 如何使用 sed/awk 替换逗号分隔字符串中的第 n 列/字段?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9838160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:50:29  来源:igfitidea点击:

How to replace the nth column/field in a comma-separated string using sed/awk?

bashreplacesedawkcsv

提问by Peter Meier

assume I have a string

假设我有一个字符串

"1,2,3,4"

Now I want to replace, e.g. the 3rd field of the string by some different value.

现在我想用一些不同的值替换,例如字符串的第三个字段。

"1,2,NEW,4"

I managed to do this with the following command:

我设法使用以下命令做到了这一点:

echo "1,2,3,4" | awk -F, -v OFS=, '{="NEW"; print }'

Now the index for the column to be replaced should be passed as a variable. So in this case

现在,要替换的列的索引应作为变量传递。所以在这种情况下

index=3

How can I pass this to awk? Because this won't work:

我怎样才能把它传递给 awk?因为这行不通:

echo "1,2,3,4" | awk -F, -v OFS=, '{$index="NEW"; print }'
echo "1,2,3,4" | awk -F, -v OFS=, '{$($index)="NEW"; print }'
echo "1,2,3,4" | awk -F, -v OFS=, '{$$index="NEW"; print }'

Thanks for your help!

谢谢你的帮助!

采纳答案by Jens

Have the shell interpolate the index in the awk program:

让 shell 在 awk 程序中插入索引:

echo "1,2,3,4" | awk -F, -v OFS=, '{$'$index'="NEW"; print }'

Note how the originally single quoted awk program is split in three parts, a single quoted beginning '{$', the interpolated index value, followed by the single quoted remainder of the program.

请注意最初的单引号 awk 程序是如何分成三个部分的,一个单引号开头的 '{$',插入的索引值,然后是程序的单引号其余部分。

回答by potong

This might work for you:

这可能对你有用:

index=3 
echo "1,2,3,4" | awk -F, -v OFS=, -v INDEX=$index '{$INDEX="NEW"; print }'

or:

或者:

index=3 
echo "1,2,3,4" | sed 's/[^,]*/NEW/'$index

回答by Lev Levitsky

Here's a seductive way to break the awkwardness:

这是sed打破awk守望的有效方法:

$ echo "1,2,3,4" | sed 's/,/\n/g' | sed -e $index's/.*/NEW/'

This is easily extendable to multiple indexes just by adding another -e $newindex's/.*/NEWNEW/'

只需添加另一个索引即可轻松扩展到多个索引 -e $newindex's/.*/NEWNEW/'

回答by baz

# This should be faster than awk or sed.
str="1,2,3,4"
IFS=','
read -a f <<< "$str"
f[2]='NEW'
printf "${f[*]}"

回答by JimR

With plain awk (I.E. Not gawk etc) I believe you'll have to use split( string, array, [fieldsep] );change the array entry of choice and then join them back together with sprintfor similar in a loop.

使用普通的 awk(IE 不是 gawk 等),我相信您必须使用split( string, array, [fieldsep] );更改选择的数组条目,然后将它们sprintf以循环方式或类似方式重新连接在一起。

gawk allows you to have a variable as a field name, $index in your example. See here.

gawk 允许您将变量作为字段名称,在您的示例中为 $index 。看到这里。

gawk is usually the default awk on Linux, so change your invocation to gawk "script" and see if it works.

gawk 通常是 Linux 上的默认 awk,因此将您的调用更改为 gawk "script" 并查看它是否有效。