如何通过管道处理多个字段运行?
How do you process multiple fields running through a pipe?
如果我有一个制表符分隔的数据文件 input.dat,格式如下:
#id acct name city age
12 100290 Sally San Francisco 24
15 102911 Jerry Sacramento 40
99 102134 Amir Eureka 82
我可以使用 cut(1)
或类似于 运行 的多个处理函数 ex:( lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age
) 每个字段作为通过管道的数据 运行s 吗?
用一个字段很容易做到这一点:
cat input.dat | cut -f1 | lookup_id > output.dat
但我想知道是否有办法针对每个字段执行此操作,并将结果重定向到 output.dat。
#id acct name city age
AA XXXXX0 SXXXX city-57 20s
AC XXXXX1 JXXXX city-29 40s
AF XXXXX4 AXXXX city-100 80s
也许一个前置问题是你能(简单地做到这一点)吗?
我也在考虑 paste(1)
可能是一种替代方法,而不是将列粘在一起,但也许有更好的方法。
用 awk 试试这样的东西:
awk -F'\t' '{system("lookup_id " ); printf("\t"); \
system("scrub_acct " ); printf("\t"); \
...
}' input.dat
通常在 awk
中处理行、列数据更容易,但由于 shell 函数的参与,最好在 shell 本身中处理。
假设 lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age
是 shell 从 stdin 读取输入的函数或脚本,您可以创建它们的数组并在循环遍历输入文件中的每条记录时调用它们:
# example shell functions
lookup_id() { read str; printf "lookup_id: %s\n" "$str"; }
scrub_acct() { read str; printf "scrub_acct: %s\n" "$str"; }
scrub_name() { read str; printf "scrub_name: %s\n" "$str"; }
lookup_city() { read str; printf "lookup_city: %s\n" "$str"; }
scrub_age() { read str; printf "scrub_age: %s\n" "$str"; }
# array of functions or scripts to be invoked
fnarr=(lookup_id scrub_acct scrub_name lookup_city scrub_age)
# main processing
while IFS=$'\t' read -ra ary; do
for ((i=0; i<${#ary[@]}; i++)); do
# call function for each field value
"${fnarr[i]}" <<< "${ary[i]}"
done
echo '============================='
done < <(tail -n +2 file)
输出:
lookup_id: 12
scrub_acct: 100290
scrub_name: Sally
lookup_city: San Francisco
scrub_age: 24
=============================
lookup_id: 15
scrub_acct: 102911
scrub_name: Jerry
lookup_city: Sacramento
scrub_age: 40
=============================
lookup_id: 99
scrub_acct: 102134
scrub_name: Amir
lookup_city: Eureka
scrub_age: 82
=============================
如果我有一个制表符分隔的数据文件 input.dat,格式如下:
#id acct name city age
12 100290 Sally San Francisco 24
15 102911 Jerry Sacramento 40
99 102134 Amir Eureka 82
我可以使用 cut(1)
或类似于 运行 的多个处理函数 ex:( lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age
) 每个字段作为通过管道的数据 运行s 吗?
用一个字段很容易做到这一点:
cat input.dat | cut -f1 | lookup_id > output.dat
但我想知道是否有办法针对每个字段执行此操作,并将结果重定向到 output.dat。
#id acct name city age
AA XXXXX0 SXXXX city-57 20s
AC XXXXX1 JXXXX city-29 40s
AF XXXXX4 AXXXX city-100 80s
也许一个前置问题是你能(简单地做到这一点)吗?
我也在考虑 paste(1)
可能是一种替代方法,而不是将列粘在一起,但也许有更好的方法。
用 awk 试试这样的东西:
awk -F'\t' '{system("lookup_id " ); printf("\t"); \
system("scrub_acct " ); printf("\t"); \
...
}' input.dat
通常在 awk
中处理行、列数据更容易,但由于 shell 函数的参与,最好在 shell 本身中处理。
假设 lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age
是 shell 从 stdin 读取输入的函数或脚本,您可以创建它们的数组并在循环遍历输入文件中的每条记录时调用它们:
# example shell functions
lookup_id() { read str; printf "lookup_id: %s\n" "$str"; }
scrub_acct() { read str; printf "scrub_acct: %s\n" "$str"; }
scrub_name() { read str; printf "scrub_name: %s\n" "$str"; }
lookup_city() { read str; printf "lookup_city: %s\n" "$str"; }
scrub_age() { read str; printf "scrub_age: %s\n" "$str"; }
# array of functions or scripts to be invoked
fnarr=(lookup_id scrub_acct scrub_name lookup_city scrub_age)
# main processing
while IFS=$'\t' read -ra ary; do
for ((i=0; i<${#ary[@]}; i++)); do
# call function for each field value
"${fnarr[i]}" <<< "${ary[i]}"
done
echo '============================='
done < <(tail -n +2 file)
输出:
lookup_id: 12
scrub_acct: 100290
scrub_name: Sally
lookup_city: San Francisco
scrub_age: 24
=============================
lookup_id: 15
scrub_acct: 102911
scrub_name: Jerry
lookup_city: Sacramento
scrub_age: 40
=============================
lookup_id: 99
scrub_acct: 102134
scrub_name: Amir
lookup_city: Eureka
scrub_age: 82
=============================