从 ls 的输出中获取与模式匹配的数字?

Gar*_*ain 5 linux ls bash filenames text-formatting

我有一个文件夹,当我ls在其中执行时,它会输出

t-1-myFirstTest.c
myFile.c
t-42-my_second_test.c
t-3-test1234.c
  .
  .
  .
mySecondFile.c
t-21-tset241.c
Run Code Online (Sandbox Code Playgroud)

我想删除此文本的所有内容,除了换行符和t-第二个-. 所以前一个的输出应该是

1
42
3
 .
 .
 .
21
Run Code Online (Sandbox Code Playgroud)

我有一个解决方案,但我认为它真的很糟糕。如果我们所说的文件夹实际上在当前目录中,那么我使用

ls | grep -o -E t-[0-9]+-[a-zA-Z0-9_]+.c | grep -o -E t-[0-9]+ | grep -o -E [0-9]+
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来完成同样的事情?

Kus*_*nda 3

解析 的输出ls是一个坏主意( 的输出ls严格用于查看)。有关详细信息,请参阅问题“为什么不*解析 `ls`? ”。

您可以按照以下方式进行操作/bin/sh

for filename in t-*-*.c; do
    [ ! -f "$filename" ] && continue
    number=${filename#t-}   # remove "t-" from start of filename
    number=${number%%-*}    # remove everything from first "-" in what remains
    printf '%s\n' "$number"
done
Run Code Online (Sandbox Code Playgroud)

这将迭代当前目录中名称与模式匹配的所有文件名t-*-*.c。对于每个名称,该t-位从一开始就被删除,然后第二个-以及之后的所有内容都通过另一个参数扩展被删除。

扩展将从的开头${variable#word}删除 (最短) 匹配,而从字符串末尾删除 (最长) 匹配。word$variable${variable%%word}word

使用bash,对文件名使用正则表达式匹配:

for filename in t-*-*.c; do
    [ ! -f "$filename" ] && continue
    if [[ "$filename" =~ ^t-([0-9]+)- ]]; then
        printf '%s\n' "${BASH_REMATCH[1]}"
    fi
done
Run Code Online (Sandbox Code Playgroud)

这将匹配并捕获每个文件名中后面的数字t-${BASH_REMATCH[1]}成功匹配后,捕获的数字组即可使用。索引指1的是正则表达式中的第一个捕获组(括号)。

对于缓慢但可能舒适(如“熟悉”)的解决方案,您可能需要调用外部命令来解析您感兴趣的字符串位:

for filename in t-*-*.c; do
    [ ! -f "$filename" ] && continue
    cut -d '-' -f 2 <<<"$filename"
done
Run Code Online (Sandbox Code Playgroud)

这假设bash您可以cut循环调用。这比使用 shell 本身内置的操作要慢得多。这里的命令被要求从传递给它的字符串中cut返回第二个分隔字段(使用“here-string”重定向)。-bash