Bash:将文件中的多行合并为一个命令参数

3
我需要将一个文件中的多行作为一个以逗号分隔的参数传递给脚本。每当我尝试使用处理文件的输出作为单个字符串时,逗号就会成为分隔符。我该怎么做?
测试用例:
[user@host]$ #Here is a word list, my target words are on lines starting with "1,"
[user@host]$ cat word_list_numbered.txt
1,lakin
2,chesterfield
3,sparkplug
4,unscrawling
5,sukkah
1,girding
2,gripeful
3,historied
4,hypoglossal
5,nonmathematician
1,instructorship
2,loller
3,containerized
4,duodecimally
5,oligocythemia
1,nonsegregation
2,expecter
3,enterrologist
4,tromometry
5,salvia
[user@host]$ #Here is a mock operation, it just outputs the number of args, I want all selected words as one argument
[user@host]$ cat operation.sh
echo "This script has $# arguments"
[user@host]$ #Here is a script that outputs the needed words as comma delimited
[user@host]$ grep '^1,' word_list_numbered.txt | tr -d '1,' | tr '\n' ',' | sed 's/,$//'        lakin,girding,instructorship,nonsegregation[user@host]$
[user@host]$ #Here is the operation script receiving that comma delimited list
[user@host]$ ./operation.sh $(grep '^1,' word_list_numbered.txt | tr -d '1,' | tr '\n' ',' | sed 's/,$//')
This script has 4 arguments
[user@host]$ #oops, too many arguments
[user@host]$ ./operation.sh foo,bar
This script has 1 arguments
[user@host]$ ./operation.sh foo bar
This script has 2 arguments
[user@host]$

详细信息:

  • 所需单词在以1开头的行中,
  • 所有单词应作为一个逗号分隔的参数传递给operation.sh,
  • 我无法控制word_list_numbered.txt的格式或operation.sh需要将所有单词作为一个逗号分隔的参数传递的要求,
  • 多次运行operation.sh并不是最优解 - 我提出这个问题是为了避免这样做。

你的 foo, bar 测试似乎涵盖了这种可能性,但由于我无法重现此问题,你的系统上 $IFS 的值是多少? - swornabsent
@swornabsent 是的,我确实走了 $IFS 路线。它显然被设置为换行符: - Adolph Trudeau
@msw 我正在尝试:选择以“1,”开头的所有行中的单词;用逗号作为分隔符将它们连接起来;并将其作为 operation.sh 的参数应用。 - Adolph Trudeau
为什么这里的每个回答都被点了一个踩? - dawg
4个回答

2
如何将awk和xargs结合起来使用?
 awk -F, -v ORS=, '$1==1{print $2}' file | xargs ./operation.sh

或者如果您介意尾随逗号:

 awk -F, -v ORS=, '$1==1{print $2}' file | sed 's/,$//' | xargs ./operation.sh

测试:

$ cat operation.sh 
echo "This script has $# arguments"
echo "$@"

$ awk -F, -v ORS=, '$1==1{print $2}' file | sed 's/,$//' | xargs ./operation.sh 
This script has 1 arguments
lakin,girding,instructorship,nonsegregation

$ cat file
1,lakin
2,chesterfield
3,sparkplug
4,unscrawling
5,sukkah
1,girding
2,gripeful
3,historied
4,hypoglossal
5,nonmathematician
1,instructorship
2,loller
3,containerized
4,duodecimally
5,oligocythemia
1,nonsegregation
2,expecter
3,enterrologist
4,tromometry
5,salvia

没有xargs,它将是这样的:
./operation.sh "$(awk -F, -v ORS=, '$1==1{print $2}' file | sed 's/,$//')"

谢谢您考虑这个问题。我认为你回答的关键部分是使用管道或在解析脚本周围加上双引号。这些管道或引号似乎强制将结果作为字符串处理。我可以在我的grep/tr/sed解析脚本周围使用管道或双引号,并获得一个参数。太棒了,谢谢! - Adolph Trudeau

1

使用bash中的命令替换来填充一个数组,然后再次使用命令替换将所有行连接成单个逗号分隔的字符串,以传递给operation.sh,这是一种替代awk的方法:

#!/bin/bash

## function simulating operation.sh
operation() { printf "%s\n" "$1"; }

a=( $(<word_list_numbered.txt) )
b="${a[0]}$(printf ",%s" ${a[@]:1} )"

operation $b

exit 0

输出

$ bash csvlist.sh
1,lakin,2,chesterfield,3,sparkplug,4,unscrawling, ..<snip>.. 5,salvia

1
给定:
$ echo "$tgt"
1,lakin
2,chesterfield
3,sparkplug
4,unscrawling
5,sukkah
1,girding
2,gripeful
3,historied
4,hypoglossal
5,nonmathematician
1,instructorship
2,loller
3,containerized
4,duodecimally
5,oligocythemia
1,nonsegregation
2,expecter
3,enterrologist
4,tromometry
5,salvia

在Perl中:
$ echo "$tgt" | perl -F',' -lane '$A[++$#A]=$F[1] if $F[0]=="1"; END{ print join(",", @A) }'
lakin,girding,instructorship,nonsegregation

谢谢您考虑这个问题。哇,如果我能用 Perl 思考,我肯定会更有效率。 - Adolph Trudeau

0

使用 awk 过滤并获取单词,然后用 paste 连接它们。

$ awk -F ',' '$1==1{print $2}' word_list_numbered.txt  | paste -s -d ',' -
lakin,girding,instructorship,nonsegregation
$ ./operation.sh "$(awk -F ',' '$1==1{print $2}' word_list_numbered.txt  | paste -s -d ',' - )"
This script has 1 arguments
$

更新:使用双引号括起来。


谢谢您考虑这个问题!这是一个非常好的使用paste的方法 - 我总是在寻找新的使用方式。不幸的是,直到我像@user000001的答案一样将输出放在双引号中,它才对我起作用。 - Adolph Trudeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接