我正在尝试在sh。
中执行以下操作这是我的档案:
synchronized
如何将4个数字拉成4个不同的变量?我现在花了大约一个小时在sed和awk手册页上,我正在旋转我的车轮。
答案 0 :(得分:2)
采用我之前的回答来使用@chepner建议的heredoc方法:
read run failures errors skipped <<EOF
$(grep -E '^Tests run: ' <file.in | tr -d -C '[:digit:][:space:]')
EOF
echo "Tests run: $run"
echo "Failures: $failures"
echo "Errors: $errors"
echo "Skipped: $skipped"
或者(把它放到shell函数中以避免覆盖&#34; $ @&#34;在脚本的持续时间内):
unset IFS # assert default values
set -- $(grep -E '^Tests run: ' <in.file | tr -d -C '[:digit:][:space:]')
run=$1; failures=$2; errors=$3; skipped=$4
请注意,这只是安全的,因为当以这种方式运行时,tr
的输出中不会出现浮点字符; set -- $(something)
通常可以更好地避免使用。
现在,如果你是为bash而不是POSIX sh编写的,你可以在shell内部执行正则表达式匹配(假设在下面你的输入文件相对较短):
#!/bin/bash
re='Tests run: ([[:digit:]]+), Failures: ([[:digit:]]+), Errors: ([[:digit:]]+), Skipped: ([[:digit:]]+)'
while IFS= read -r line; do
if [[ $line =~ $re ]]; then
run=${BASH_REMATCH[1]}
failed=${BASH_REMATCH[2]}
errors=${BASH_REMATCH[3]}
skipped=${BASH_REMATCH[4]}
fi
done <file.in
如果你的输入文件不很短,那么用grep预过滤它可能会更有效率,从而将最后一行更改为:
done < <(egrep -E '^Tests run: ' <file.in)
答案 1 :(得分:1)
根据输入文件的格式,您可以在此处的文档中捕获grep
的输出,然后将其与read
分成四个部分进行后处理。
IFS=, read part1 part2 part3 part4 <<EOF
$(grep '^Tests run' input.txt)
EOF
然后从每个部分中删除不需要的前缀。
run=${part1#*: }
failures=${part2#*: }
errors=${part3#*: }
skipped=${part4#*: }
答案 2 :(得分:0)
假设文件中只有一行以Tests run:
开头,并且该文件名为foo.txt
,则以下命令将创建4个可以使用的shell变量:
eval $(awk 'BEGIN{ FS="(: |,)" }; /^Tests run/{ print "TOTAL=" $2 "\nFAIL=" $4 "\nERROR=" $6 "\nSKIP=" $8 }' foo.txt); echo $TOTAL; echo $SKIP; echo $ERROR; echo $FAIL
echo $TOTAL; echo $SKIP; echo $ERROR; echo $FAIL
只是为了证明环境变量存在且可以使用。
更可读的awk脚本是:
BEGIN { FS = "(: |,)" }
/^Tests run/ {
print "TOTAL=" $2 "\nFAIL=" $4 "\nERROR=" $6 "\nSKIP=" $8
}
FS = "(: |,)"
告诉awk考虑&#34; :
&#34;或&#34; ,
&#34;作为字段分隔符。
然后eval
命令将作为命令读取awk脚本的结果,并因此创建4个环境变量。
注意:由于使用了eval
,您必须信任foo.txt
文件的内容,因为可以伪造以Tests run:
开头的行之后可以有命令。
您可以通过在awk脚本中使用更严格的正则表达式来改善这一点:/^Tests run: \d+, Failures: \d+, Errors: \d+, Skipped: \d+$/
完整的命令将是:
eval $(awk 'BEGIN{ FS="(: |,)" }; /^Tests run: \d+, Failures: \d+, Errors: \d+, Skipped: \d+$/{ print "TOTAL=" $2 "\nFAIL=" $4 "\nERROR=" $6 "\nSKIP=" $8 }' foo.txt); echo $TOTAL; echo $SKIP; echo $ERROR; echo $FAIL
答案 3 :(得分:-1)
有更短的版本,但这一个“显示”每一步。
#!/bin/bash
declare -a arr=`grep 'Tests ' a | awk -F',' '{print $1 "\n" $2 "\n" $3 "\n" $4}' | sed 's/ //g' | awk -F':' '{print $2}'`
echo $arr
for var in $arr
do
echo $var
done