我有一个数字列表(无重复),val_str="11 22 33"
如果需要,可以将其存储为数组,例如:val_arr=(11 22 33)
。
我有第二个数字列表,这些数字来自制表符分隔文件中的字段。如果需要的话,我可以使用awk
.以下是一些玩具数据:
echo -e "66\n55\n99\n33\n11\n88\n77\n22\n33" > list
val_arr
我想找到第一个出现在 中的元素的值list
。的某些元素可能val_arr
不会出现在 中list
。如果 的所有元素val_arr
都出现在 中,则下面的代码有效list
,但如果不是这种情况,则失败,例如 if val_arr=(11 44 22 33)
。
val_arr=(11 22 33)
echo -e "66\n55\n99\n33\n11\n88\n77\n22\n33" > list
pos_arr=()
for i in ${!val_arr[@]}; do
list_pos=$(grep -nm 1 ${val_arr[$i]} list | cut -f1 -d:)
pos_arr+=( ${list_pos} )
done
pos1=$(echo ${pos_arr[@]} | tr ' ' '\n' | awk 'NR==1 {min=$0} NR>1 && $1<min {min=$1; pos=NR} END {print pos}')
pos0=$(( pos1 - 1 ))
val=${val_arr[$pos0]}
在两者的情况下val_arr=(11 22 33)
,val_arr=(11 44 22 33)
我希望脚本返回33
。
我的问题是:
- 有一个更好的方法吗?
- 有没有办法使此代码对缺失值具有鲁棒性(比将所有值附加到with
val_arry
的末尾更优雅)?list
echo ${pos_arr[@]} | tr ' ' '\n' >> list
谢谢!
PS 感谢@Adrian Frühwirth 提供了awk
上面的代码:
https://stackoverflow.com/questions/16610162/bash-return-position-of-the-smallest-entry-in-an-array
答案1
val_arr
变成 grep 模式或表达式列表怎么样
$ echo "${val_arr[@]/#/-e}"
-e11 -e44 -e22 -e33
并直接使用它?
$ grep -wFm1 "${val_arr[@]/#/-e}" list
33
答案2
我只需使用grep
数组并将其转换为字符串:
#!/bin/bash
val_arr=(11 22 33)
grep_string=$(tr ' ' '|' <<<"${val_arr[@]}")
first_found=$(grep -wEm1 "$grep_string" list);
if [[ -z $first_found ]]; then
echo "None of the numbers were found"
else
echo "Found: $first_found"
fi
该tr
命令会将数组转换为由 分隔的元素列表|
:
$ grep_string=$(tr ' ' '|' <<<"${val_arr[@]}")
$ echo $grep_string
11|22|33
然后可以将其传递给grep -E
.使用的选项是:
-E
:启用扩展正则表达式,以便我们可以用来|
表示“OR”。-w
: 只匹配整个单词,因此3
不匹配33
。您也可以使用-x
(匹配整行),具体取决于您的输入。-m1
:第一场比赛后停止。
如果您还需要文件中的位置,请添加-n
,以便它也将打印行号。