我想根据条件从数据帧中过滤行(如果它们存在于列表中)。到目前为止我已经尝试过这个事情。但我得到了意想不到的结果。数据正在被复制,但我无法理解它
#!/bin/bash
arr_country=(AL AD AM AT BY BE BA BG CH)
for element in "${arr_country[@]}"
do
awk -F '\t' '{if($1==$element){print}}' abc.txt >>xyz.txt
done
echo
echo "Data Transferred"
示例数据集包含有关不同国家/地区的信息,第一列代表国家/地区名称。我想根据给定的数组对数据集进行子集化。
答案1
element
不是awk
变量。
要将 shell 变量的值导入到awk
脚本中,您可以使用
awk -v variable="$value" '{ script goes here }'
在上面的示例中,调用的变量variable
将获取名为 的 shell 变量的值value
。您可以variable
在awk
脚本中使用而不用前缀$
.
请注意,如果您为变量添加前缀$
in awk
,则假定该变量的值是正整数,并且它引用当前输入记录中的特定字段。$element
例如,该表达式将为您提供字段编号的值element
(就像为$1
您提供第一个字段的值并$NF
为您提供最后一个字段的值,其中NF
是表示当前记录中字段数量的内置变量) 。
如果element
在代码中未设置awk
,$element
则将扩展为$0
完整行。如果第一个制表符分隔字段是该行中唯一的内容,那么您的代码将打印整行。
您的awk
脚本也可以缩短为
awk -F '\t' -v e="$element" '$1 == e'
或者,您可以将整个内容替换为
arr_country=(AL AD AM AT BY BE BA BG CH)
( IFS='|'; grep -E "^(${arr_country[*]})\>" ) <abc.txt >xyz.txt
或者,
grep -E '^(AL|AD|AM|AT|BY|BE|BA|BG|CH)\>' <abc.txt >xyz.txt
参数${arr_country[*]}
替换将扩展为单个字符串,该字符串由数组的值组成,并以 的第一个字符分隔$IFS
。这将创建一个与上面显示的第二个相同的正则表达式grep
。 \>
将匹配单词末尾的零宽度空格(以便^AA\>
匹配AA
行首,但不匹配AAA
)。
唯一的区别是,与 的 shell 循环解决方案相比,结果的顺序可能不同awk
。
消除 shell 循环的不同方法(假设 的默认值$IFS
):
arr_country=(AL AD AM AT BY BE BA BG CH)
awk -v c="${arr_country[*]}" -F '\t' '
BEGIN { n=split(c,a," "); for (i=1;i<=n;++i) country[a[i]] }
$1 in country' <abc.txt >xyz.txt
在这里,我们将 的元素arr_country
作为空格分隔的字符串赋予awk
变量 中的代码c
。在开始从输入读取之前,c
字符串被分成几部分,并且每部分都被制作成关联数组中的一个键country
。如果第一个字段是该数组中的键,则打印该行。