使用 shell 脚本将另一个字段上的函数结果附加到 csv 中,awk
Appending result of function on another field into csv using shell script, awk
我有一个 csv 文件作为临时变量存储在 shell 脚本 (*.sh) 中。
假设数据如下所示:
Account,Symbol,Price
100,AAPL US,200
102,SPY US,500
我想添加第四列 "Type",它是 shell 函数 "foobar" 的结果。 运行 来自命令行或 shell 脚本本身:
$ foobar "AAPL US"
"Stock"
$ foobar "SPY US"
"ETF"
如何将此列添加到我的 csv 中,并通过调用将第二列作为参数的 foobar 来填充它?澄清一下,这是我的理想结果 post-script:
Account,Symbol,Price,Type
100,AAPL US,200,Common Stock
102,SPY US,500,ETF
我在网上看到很多例子涉及使用 awk 添加这样的列,并用固定值、条件值、其他列的数学推导等填充新列 - 但没有在另一个字段上调用函数和存储它的输出。
awk
救援!
$ echo "Account,Symbol,Price
100,AAPL US,200
102,SPY US,500" |
awk -F, 'NR>1{cmd="foobar "; cmd | getline type} {print [=10=] FS (NR==1?"Type":type)}'
不确定是否需要引用 foobar
的输入
您可以使用这个 awk
:
export -f foobar
awk 'BEGIN{FS=OFS=","} NR==1{print [=10=], "Type"; next} {
cmd = "foobar \"" "\""; cmd | getline line; close(cmd);
print [=10=], line
}' file.csv
Account,Symbol,Price,Type
100,AAPL US,200,Common Stock
102,SPY US,500,ETF
不使用awk
的另一种方式:
paste -d, input.csv <({ read; printf "Type\n"; while IFS=, read -r _ s _; do foobar "$s"; done; } < input.csv)
@anubhavas 的回答是一个很好的方法,所以请不要更改已接受的答案,因为我只是将其作为答案发布,因为它太大并且需要格式化以适合评论。
FWIW 我会把他的 awk 脚本写成:
awk '
BEGIN { FS=OFS="," }
NR==1 { type = "Type" }
NR > 1 {
cmd = "foobar 7" "7"
type = ((cmd | getline line) > 0 ? line : "ERROR")
close(cmd)
}
{ print [=10=], type }
' file.csv
至:
- 更好地保护 $2 免受 shell 扩展,并且
- 防止静默打印先前的值 if/when
cmd | getline
失败,并且
- 将打印语句合并为 1 行,以便轻松更改所有输出行 if/when 必要
我有一个 csv 文件作为临时变量存储在 shell 脚本 (*.sh) 中。
假设数据如下所示:
Account,Symbol,Price
100,AAPL US,200
102,SPY US,500
我想添加第四列 "Type",它是 shell 函数 "foobar" 的结果。 运行 来自命令行或 shell 脚本本身:
$ foobar "AAPL US"
"Stock"
$ foobar "SPY US"
"ETF"
如何将此列添加到我的 csv 中,并通过调用将第二列作为参数的 foobar 来填充它?澄清一下,这是我的理想结果 post-script:
Account,Symbol,Price,Type
100,AAPL US,200,Common Stock
102,SPY US,500,ETF
我在网上看到很多例子涉及使用 awk 添加这样的列,并用固定值、条件值、其他列的数学推导等填充新列 - 但没有在另一个字段上调用函数和存储它的输出。
awk
救援!
$ echo "Account,Symbol,Price
100,AAPL US,200
102,SPY US,500" |
awk -F, 'NR>1{cmd="foobar "; cmd | getline type} {print [=10=] FS (NR==1?"Type":type)}'
不确定是否需要引用 foobar
您可以使用这个 awk
:
export -f foobar
awk 'BEGIN{FS=OFS=","} NR==1{print [=10=], "Type"; next} {
cmd = "foobar \"" "\""; cmd | getline line; close(cmd);
print [=10=], line
}' file.csv
Account,Symbol,Price,Type
100,AAPL US,200,Common Stock
102,SPY US,500,ETF
不使用awk
的另一种方式:
paste -d, input.csv <({ read; printf "Type\n"; while IFS=, read -r _ s _; do foobar "$s"; done; } < input.csv)
@anubhavas 的回答是一个很好的方法,所以请不要更改已接受的答案,因为我只是将其作为答案发布,因为它太大并且需要格式化以适合评论。
FWIW 我会把他的 awk 脚本写成:
awk '
BEGIN { FS=OFS="," }
NR==1 { type = "Type" }
NR > 1 {
cmd = "foobar 7" "7"
type = ((cmd | getline line) > 0 ? line : "ERROR")
close(cmd)
}
{ print [=10=], type }
' file.csv
至:
- 更好地保护 $2 免受 shell 扩展,并且
- 防止静默打印先前的值 if/when
cmd | getline
失败,并且 - 将打印语句合并为 1 行,以便轻松更改所有输出行 if/when 必要