我有一个文件名列表,我试图在sil.
和.asc
之间提取索引并将它们放在列表中,而我不在列表中重复索引。以下是我的文件列表的一部分。
ellip5.0.apo.3.sil.16.asc
ellip5.0.apo.3.sil.7.asc
ellip5.0.apo.3.sil.8.asc
ellip5.0.apo.4.sil.3.asc
ellip5.0.apo.4.sil.14.asc
ellip5.0.apo.4.sil.5.asc
ellip5.0.apo.4.sil.6.asc
ellip5.0.apo.4.sil.7.asc
ellip5.0.apo.4.sil.8.asc
ellip5.0.apo.5.sil.3.asc
ellip5.0.apo.5.sil.14.asc
ellip5.0.apo.5.sil.5.asc
ellip5.0.apo.5.sil.6.asc
ellip5.0.apo.5.sil.7.asc
ellip5.0.apo.5.sil.8.asc
ellip5.0.apo.6.sil.3.asc
ellip5.0.apo.6.sil.4.asc
ellip5.0.apo.6.sil.5.asc
ellip5.0.apo.6.sil.16.asc
ellip5.0.apo.6.sil.7.asc
ellip5.0.apo.6.sil.8.asc
ellip5.0.apo.7.sil.13.asc
ellip5.0.apo.7.sil.4.asc
ellip5.0.apo.7.sil.5.asc
以下代码是我尝试制作列表但不起作用
args=()
containsElement () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
for MYVAR in "ellip*.asc"
j=0
for i in $(ls ellip*.asc)
do
INDEX=`echo $i | grep -oE 'sil.[^/]+.asc' | cut -c5- | rev | cut -c5- | rev`
listcontains INDEX "${args[@]}"
if [ $? == 1 ];then
args[j]=$INDEX
j=$(($j + 1))
echo $INDEX
fi
done
echo ${args[@]}
任何建议将不胜感激.. 我的预期清单是:
16 7 8 3 14 5 6 16 4 13
,最好是排序列表。
答案 0 :(得分:2)
您可以在BASH 4中使用此脚本:
# declare an associative array
declare -A arr
for f in ellip*.asc; do
f="${f/#*sil.}"
f="${f%.asc}"
arr["$f"]=1
done
# print sorted index values
printf "%s\n" "${!arr[@]}" | sort -n
3
4
5
6
7
8
13
14
16
在不支持关联数组的旧BASH中使用:
declare -a arr
for f in ellip*.asc; do
f="${f/#*sil.}"
f="${f%.asc}"
arr+=("$f")
done
sort -un <(printf "%s\n" "${arr[@]}")
<强>输出:强>
3
4
5
6
7
8
13
14
16
答案 1 :(得分:2)
我会使用像
这样的东西ls ellip*.asc | cut -f 6 -d . | sort -nu
cut
程序正好符合您的要求,选择由.
的分隔符分隔的第6个字段。
答案 2 :(得分:0)
如果您不担心使用某些实用程序(您可能不会这样做,因为您的示例中已有grep
,cut
和rev
,那么你可以在一个oneliner上做到这一点:
arr=($(sed 's/ /\n/g' <<< $(echo *.sil.*.asc) |cut -d. -f6 |sort -n |uniq))
这将首先获取您的文件列表(请注意,您需要echo
将文件列表输入sed
,因为路径名在<<<
之后不会展开,将其分成行,选择第6个字段,将分隔符设置为.
,然后从每个字段中选择一个uniqe值(另请注意uniq
需要排序列表作为输入)。然后将此列表分配给数组。
另请注意,在您的示例中,您有:
...
for i in $(ls ellip*.asc)
do
...
在这里,您解析ls
的输出,通常应避免使用see here。特别是在这种情况下,它可能是安全的,因为您的文件名具有固定的格式。