我试图在每个循环中获取这个词。我不知道如何插入i
到print $2
.
while [ $i -lt 4 ]
do
A=$(awk -F_ '{print $2}' <<< 'one_two_test_three')
echo $A
done
显然,这将输出:
two
two
two
two
我想要的是:
one
two
test
three
我试过:
A=$(awk -F_ '{print $($i)}' <<< 'one_two_test_three')
没用。
答案1
正确的方法是通过( ) 选项将bash/shell
变量awk
作为参数传递到脚本中:-v
variable
i=1;
while [ $i -lt 5 ]; do
A=$(awk -v i="$i" -F_ '{ print $i }' <<< 'one_two_test_three')
echo $A
((i++))
done
输出:
one
two
test
three
答案2
不需要 shell 循环来解析数据:
$ awk -F '_' '{ for (i=1; i<=NF; ++i) print $i }' <<<'one_two_test_three'
one
two
test
three
该脚本将输入解析为以_
- 分隔的列表并打印每个字段。
较短:
$ awk -F '_' 'BEGIN { OFS="\n" } { $1=$1 } 1' <<< 'one_two_test_three'
one
two
test
three
这将输出字段分隔符设置为换行符,然后在打印记录之前强制重新形成整个记录(插入新的分隔符)。
较短:
$ tr '_' '\n' <<<'one_two_test_three'
one
two
test
three
循环访问数据:
tr '_' '\n' <<<'one_two_test_three' |
while read -r word; do
printf 'Got "%s"\n' "$word"
done
这样,您就不会多次调用用于解析数据的实用程序。
答案3
假设这些值没有换行符,那么:您的代码只需进行最少的更改即可使其正常工作:shebang 必须是#!/bin/bash
(ksh 或 zsh),因为您正在使用<<<
.
i=1
while [ "$i" -le 4 ]
do
A=$(awk -v var="$i" -F_ '{print $var}' <<< 'one_two_test_three')
echo "$A"
i=$((i+1))
done
但是,由于字符串来自 shell,因此可以简化为:
IFS=_ read v1 v2 v3 v4 <<<'one_two_test_three'
printf '%s\n' "$v1" "$v2" "$v3" "$v4"
并使用值数组(可变数量的值):
#!/bin/bash
IFS=_ read -a v <<<'one_two_test_three'
printf '%s\n' "${v[@]}"
如果需要使用更简单的 shell:
#!/bin/sh
IFS=_ read v1 v2 v3 v4 <<-_expandvar_
one_two_test_three
_expandvar_
printf '%s\n' "$v1" "$v2" "$v3" "$v4"
当然,如果不需要设置变量,在脚本中设置 IFS 的值也没有问题:
#/bin/sh
a='one_two_test_three'
IFS=_
set -f
printf '%s\n' $a
请注意,该变量不带引号使用,这可能不安全。