GNU 与自定义脚本并行进行字符串比较
GNU parallel with custom script doing string comparison
以下 script.sh
将字符串的一部分(来自 stdin
的 cat
一个 csv 文件)与定义的字符串进行比较,并以特定格式报告差异
#!/usr/bin/env bash
reference="ABCDEFG"
ref_transp=$(echo "$reference" | sed -e 's/\(.\)/\n/g')
while read line; do
line_transp=$(echo "$line" | cut -d',' -f2 | sed -e 's/\(.\)/\n/g')
output=$(paste -d ' ' <(echo "$ref_transp") <(echo "$line_transp") | grep -vnP '([A-Z]) ' | sed -E 's/([0-9][0-9]*):([A-Z]) ([A-Z]*)//' | grep '^[A-Z][0-9][0-9]*[A-Z*]$')
echo "$(echo ${line:0:35}, $output)"
done < "${1:-/dev/stdin}"
它打算在格式非常大的文件中的多行上执行
XYZ,ABMDEFG
当我在管道中使用它时效果很好:
cat large_file | ./find_something.sh
但是,当我尝试将它与 parallel
一起使用时,出现此错误:
$ cat large_file | parallel ./find_something.sh
./find_something.sh: line 9: XYZ, ABMDEFG : No such file or directory
这是什么原因造成的?如果我之后想将输出重定向到单个文件,parallel
是否应该为这样的事情工作?
不太重要的旁注:我为我的字符串比较方法感到自豪,但如果有人有更快的方法来比较 ABCDEFG
和 XYZ,ABMDEFG
以获得 XYZ,C3M
我也很高兴听到这个消息。
编辑:
我应该说,我还想保留输出中每一行的顺序,与输入相对应。可以使用并行吗?
您的脚本接受来自文件的输入(默认为标准输入),而 parallel
将输入作为参数传递,而不是通过标准输入。从这个意义上说,parallel
更接近于 xargs
。
据推测,您希望 large_file
中的每一行作为一个单元处理,可能是并行处理。
这意味着您需要您的脚本一次只处理这样的一行,并让 parallel
多次调用您的脚本,每行一次。
所以你的脚本应该是这样的:
#!/usr/bin/env bash
reference="ABCDEFG"
ref_transp=$(echo "$reference" | sed -e 's/\(.\)/\n/g')
line=""
line_transp=$(echo "$line" | cut -d',' -f2 | sed -e 's/\(.\)/\n/g')
output=$(paste -d ' ' <(echo "$ref_transp") <(echo "$line_transp") | grep -vnP '([A-Z]) ' | sed -E 's/([0-9][0-9]*):([A-Z]) ([A-Z]*)//' | grep '^[A-Z][0-9][0-9]*[A-Z*]$')
echo "$(echo ${line:0:35}, $output)"
然后你可以重定向到一个文件如下:
cat large_file | parallel ./find_something.sh > output_file
-k
保持顺序。
#!/usr/bin/env bash
doit() {
reference="ABCDEFG"
ref_transp=$(echo "$reference" | sed -e 's/\(.\)/\n/g')
while read line; do
line_transp=$(echo "$line" | cut -d',' -f2 | sed -e 's/\(.\)/\n/g')
output=$(paste -d ' ' <(echo "$ref_transp") <(echo "$line_transp") | grep -vnP '([A-Z]) ' | sed -E 's/([0-9][0-9]*):([A-Z]) ([A-Z]*)//' | grep '^[A-Z][0-9][0-9]*[A-Z*]$')
echo "$(echo ${line:0:35}, $output)"
done
}
export -f doit
cat large_file | parallel --pipe -k doit
#or
parallel --pipepart -a large_file --block -10 -k doit
以下 script.sh
将字符串的一部分(来自 stdin
的 cat
一个 csv 文件)与定义的字符串进行比较,并以特定格式报告差异
#!/usr/bin/env bash
reference="ABCDEFG"
ref_transp=$(echo "$reference" | sed -e 's/\(.\)/\n/g')
while read line; do
line_transp=$(echo "$line" | cut -d',' -f2 | sed -e 's/\(.\)/\n/g')
output=$(paste -d ' ' <(echo "$ref_transp") <(echo "$line_transp") | grep -vnP '([A-Z]) ' | sed -E 's/([0-9][0-9]*):([A-Z]) ([A-Z]*)//' | grep '^[A-Z][0-9][0-9]*[A-Z*]$')
echo "$(echo ${line:0:35}, $output)"
done < "${1:-/dev/stdin}"
它打算在格式非常大的文件中的多行上执行
XYZ,ABMDEFG
当我在管道中使用它时效果很好:
cat large_file | ./find_something.sh
但是,当我尝试将它与 parallel
一起使用时,出现此错误:
$ cat large_file | parallel ./find_something.sh
./find_something.sh: line 9: XYZ, ABMDEFG : No such file or directory
这是什么原因造成的?如果我之后想将输出重定向到单个文件,parallel
是否应该为这样的事情工作?
不太重要的旁注:我为我的字符串比较方法感到自豪,但如果有人有更快的方法来比较 ABCDEFG
和 XYZ,ABMDEFG
以获得 XYZ,C3M
我也很高兴听到这个消息。
编辑:
我应该说,我还想保留输出中每一行的顺序,与输入相对应。可以使用并行吗?
您的脚本接受来自文件的输入(默认为标准输入),而 parallel
将输入作为参数传递,而不是通过标准输入。从这个意义上说,parallel
更接近于 xargs
。
据推测,您希望 large_file
中的每一行作为一个单元处理,可能是并行处理。
这意味着您需要您的脚本一次只处理这样的一行,并让 parallel
多次调用您的脚本,每行一次。
所以你的脚本应该是这样的:
#!/usr/bin/env bash
reference="ABCDEFG"
ref_transp=$(echo "$reference" | sed -e 's/\(.\)/\n/g')
line=""
line_transp=$(echo "$line" | cut -d',' -f2 | sed -e 's/\(.\)/\n/g')
output=$(paste -d ' ' <(echo "$ref_transp") <(echo "$line_transp") | grep -vnP '([A-Z]) ' | sed -E 's/([0-9][0-9]*):([A-Z]) ([A-Z]*)//' | grep '^[A-Z][0-9][0-9]*[A-Z*]$')
echo "$(echo ${line:0:35}, $output)"
然后你可以重定向到一个文件如下:
cat large_file | parallel ./find_something.sh > output_file
-k
保持顺序。
#!/usr/bin/env bash
doit() {
reference="ABCDEFG"
ref_transp=$(echo "$reference" | sed -e 's/\(.\)/\n/g')
while read line; do
line_transp=$(echo "$line" | cut -d',' -f2 | sed -e 's/\(.\)/\n/g')
output=$(paste -d ' ' <(echo "$ref_transp") <(echo "$line_transp") | grep -vnP '([A-Z]) ' | sed -E 's/([0-9][0-9]*):([A-Z]) ([A-Z]*)//' | grep '^[A-Z][0-9][0-9]*[A-Z*]$')
echo "$(echo ${line:0:35}, $output)"
done
}
export -f doit
cat large_file | parallel --pipe -k doit
#or
parallel --pipepart -a large_file --block -10 -k doit