使用 bash -c 逐行解析

Line by line parsing with bash -c

在bash中,我逐行解析文件并提取第一和第二字段,如下所示:

$ cat myfile
a1 1
a2 2
a3 3
a4

$ while read -r first second; do echo first is $first second is $second; done < myfile
first is a1 second is 1
first is a2 second is 2
first is a3 second is 3
first is a4 second is

现在,我需要将上面的命令放在bash -c中,因为它将通过kubectl exec执行。它没有按预期工作,只评估它在最后一行解析的内容:

$ bash -c "while read -r first second; do echo first is $first second is $second; done < myfile"
first is a4 second is
first is a4 second is
first is a4 second is
first is a4 second is

这里缺少什么?

谢谢!

您的参数在父级 shell 中扩展,更改引号或转义参数扩展:

$ bash -c 'while read -r first second; do echo first is $first second is $second; done < myfile'

$ bash -c "while read -r first second; do echo first is $first second is $second; done < myfile"

请注意,您几乎应该始终将参数扩展括在双引号中:

echo "$a"

而不是

echo $a

避免分词和路径名扩展。

考虑以下示例,在 POSIX shell 中:

a="hello *"; echo $a;

a="hello *"; echo "$a";

所以这会让你的脚本最终看起来像:

$ bash -c 'while read -r first second; do echo first is "$first" second is "$second"; done < myfile'

如果您不想处理复杂的 shell double-qouting,首先定义一个函数,您可以在其中手动输入代码,shellcheck 也可以帮助您输入正确的代码:

f() { 
   while IFS=' ' read -r first second; do
        echo "first is $first second is $second";
   done
} 

然后做:

printf "%q\n" "$(declare -f f); f"
$'f () \n{ \n    while IFS=\' \' read -r first second; do\n        echo "first is $first second is $second";\n    done\n}; f'

declare 以可重复使用的形式打印函数定义,然后我们 f 调用该函数。然后您可以复制输出并在 shell:

中重新使用它
bash -c $'f () \n{ \n    while IFS=\' \' read -r first second; do\n        echo "first is $first second is $second";\n    done\n}; f'

$'...' 特定于 Bash C 引用样式,因此在需要时使用与 printf %q 不同的引用函数。