for 循环内的 awk 命令

for 循环内的 awk 命令

awk我尝试在循环内使用命令,但没有成功for

我有一个变量,其中包含一系列字符串,我想用它们来剪切以awk获取数据。

我知道该怎么做,但我真正想要的是连续剪切数据。

所以我有这个变量:

var="data1,data2,data3"

我现在就在这里:

for ((i=1; i<=3; i++))
do
    echo $(awk -F, '{print $1}' <<< $var)
done

我尝试$1用循环替换$i,但没有成功。

答案1

您可以通过在 awk 脚本中使用双引号将 shell 变量注入其中来完成您想要做的事情。您仍然想$在其中保留一个文字,可以通过使用反斜杠转义它来实现:

echo $(awk -F, "{print \$$i}" <<<$var)

这将在每次迭代中扩展,$i和,因此 awk 将看到,和 ,这将使其扩展每个字段。123$1$2$3

另一种可能性是使用以下标志将 shell 变量作为 awk 变量注入-v

echo $(awk -F, -v i="$i" '{print $i}' <<<$var)

分配 awk 变量到同名的 shell 变量的内容。 awk 中的变量不使用 a $,它用于字段,因此$i足以引用-第一个字段如果是 awk 中的变量。

为 awk 变量赋值-v通常是一种更安全的方法,特别是当它可以包含任意字符序列时,在这种情况下,内容将作为 awk 代码执行违背您的意图的风险较小。但由于在您的情况下变量保存单个整数,因此不必担心。

for另一种选择是在 awk 本身中使用循环。有关如何执行此操作的更多详细信息,请参阅 awk 文档(或搜索此站点)。

答案2

在这种情况下使用似乎有点过多,那么使用 a和 while 循环awk怎么样:tr

tr , '\n' <<<"$var" | while read; do
  echo $REPLY
done

输出:

data1
data2
data3

答案3

#!/bin/sh

var='data1,data2,data3'

unset data
while [ "$var" != "$data" ]; do
    data=${var%%,*}    # delete first comma and the bit after it
    var=${var#*,}      # delete bit up to first comma (and the comma)

    printf 'data = "%s"\n' "$data"
done

在这里,我们使用变量替换从变量的值中获取每个连续的逗号分隔数据字段vardata循环中的第一个赋值将删​​除$var第一个逗号之后的所有内容。然后修改该var变量,以便删除第一个逗号之前的第一位。

这一直持续到"$var" = "$data"这意味着不能对字符串执行任何操作。

这种方法允许我们处理包含嵌入换行符的逗号分隔数据字符串:

var='line1
line2,data2,last bit
goes here'

使用上述值var,上面的脚本将输出

data = "line1
line2"
data = "data2"
data = "last bit
goes here"

不关心嵌入的换行符;你很少必须循环调用awk.

请注意,awk非常乐意将字符串读取为一组逗号分隔的字段,并且它能够循环这些字段:

printf '%s\n' "$var" |
awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'

使用var='data1,data2,data3',这将打印

data1
data2
data3

另一种 shell 解决方案利用IFS变量将$var值拆分为位,同时还使用set -f禁用文件名扩展:

set -f
oldIFS=$IFS; IFS=','

set -- $var

IFS=$oldIFS; unset oldIFS
set +f

for data do
    printf 'data = "%s"\n' "$data"
done

答案4

可以接受j(作为变量)和$j(作为字段索引):

for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done

$i在示例中“混淆”awk使用哪一个(shell 或其自己的变量 - 优先),因为两者都用$前缀引用。

笔记

作为“便携式”脚本标准的 shell 不支持:

(( i=1; i<=3; i++; ))<<< $var构建

此外,您还可以考虑使用循环seq中的命令for来更好地控制数字序列生成(如果可用)。

相关内容