提取字符串列表的某些部分并将其设置在列表中而不重复

时间:2015-07-21 22:01:11

标签: linux bash list

我有一个文件名列表,我试图在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

,最好是排序列表。

3 个答案:

答案 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)

如果您不担心使用某些实用程序(您可能不会这样做,因为您的示例中已有grepcutrev ,那么你可以在一个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。特别是在这种情况下,它可能是安全的,因为您的文件名具有固定的格式。