运行 ${ls ... | 时出现错误替换sed ...} 与 bash

运行 ${ls ... | 时出现错误替换sed ...} 与 bash

我收到以下错误:

./assemblyDB.116.las
test.sh: line 9: ${ls $filename | sed 's/assemblyDB.//' | sed 's/.las//'}: bad substitution

这是脚本:

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   no=${ls $filename | sed 's/assemblyDB.//' | sed 's/.las//'}
   echo $no
done

答案1

${ ... }(花括号)标记了几种参数扩展,其中最简单的就是扩展变量的值。代码中大括号内的内容不是有效的参数名称或任何其他扩展,因此 shell 会抱怨。

您似乎想要命令替换,为此,语法是$( ... )(正则括号)。

另外,lsinls $filename | sed...似乎有点不必要,变量扩展为您的文件名,然后ls将其传递。你可以直接用它echo "$filename" | sed ...来代替。

也就是说,您可以直接在 shell 中进行这些修改:

no="${filename/assemblyDB.}"   # remove first match
no="${no/.las}"

或者,使用标准运算符:

no="${filename#assemblyDB.}"   # remove from start of string
no="${no%.las}"                # remove from end of string

如果您确实运行sed,您可能需要注意.匹配正则表达式中的任何字符,因此用反斜杠引用它会更正确。您还可以为一个sed实例提供两个命令:sed -e 's/assemblyDB\.//' -e 's/\.las//'.

然后for filename in $(find . -type f -name "assemblyDB.*.las"); do就有了所有的问题解析 ls主要是文件名中的空格和通配符会破坏它。在 ksh/Bash/zsh 中,您可以在 shell 中执行整个循环:

shopt -s globstar         # in Bash
for filename in **/assemblyDB.*.las; do
    ...

答案2

命令替换(第 3 行)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   no=$(ls $filename | sed 's/assemblyDB.//' | sed 's/.las//')
   echo $no
done

正如已经指出的那样,相当于(第 3 行,否ls

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   no=$(echo $filename | sed 's/assemblyDB.//' | sed 's/.las//')
   echo $no
done

或更短(第 4 行消失,现在直接回显)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   echo $filename | sed 's/assemblyDB.//' | sed 's/.las//'
done

sed 命令可以简化为(第 3 行)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   echo $filename | sed 's/assemblyDB.//;s/.las//'
done

或者用 sed 提取中间部分:(仍然是第 3 行)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   echo $filename | sed -r 's/.*assemblyDB.(.*).las/\1/'" 
done

现在 find-iterator 而不是 for-iterator:(第 1 到 3、4 行消失了)

find . -type f -name "assemblyDB.*.las" -printf "%f\n" -exec sh -c "
   echo {} | sed -r 's/.*assemblyDB.(.*).las/\1/'"  ";"

assemblyDB.11.las
11
assemblyDB.9.las
9
assemblyDB.10.las
10

如果您的文件名采用这样或类似的顺序,则以下方法也可能有效:

for i in {8..12} ; do ls assemblyDB.$i.las && echo $i ; done 2>/dev/null

assemblyDB.9.las
9
assemblyDB.10.las
10
assemblyDB.11.las
11

(包括 8 和 12,以演示序列中丢失的文件)。

答案3

而不是${}使用反引号`[键盘上 Escape 下方的按钮。]

相关内容