我有一个文件夹,当我ls
在其中执行时,它输出
t-1-myFirstTest.c
myFile.c
t-42-my_second_test.c
t-3-test1234.c
.
.
.
mySecondFile.c
t-21-tset241.c
我想删除该文本的所有内容,除了换行符以及t-
和 第二个之间的数字-
。所以前一个的输出应该是
1
42
3
.
.
.
21
我有一个解决方案,但我认为这非常糟糕。如果我们正在讨论的文件夹实际上在当前目录中,那么我使用
ls | grep -o -E t-[0-9]+-[a-zA-Z0-9_]+.c | grep -o -E t-[0-9]+ | grep -o -E [0-9]+
有更好的方法来完成同样的事情吗?
答案1
解析 的输出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
这将迭代当前目录中名称与模式匹配的所有文件名t-*-*.c
。对于每个名称,该t-
位从一开始就被删除,然后第二个-
以及之后的所有内容都通过另一个参数扩展被删除。
扩展将从中${variable#word}
删除(最短)匹配word
开始of $variable
, while将从中${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
t-
这将匹配并捕获每个文件名中后面的数字。${BASH_REMATCH[1]}
成功匹配后,捕获的数字组即可使用。索引指1
的是正则表达式中的第一个捕获组(括号)。
对于缓慢但可能舒适(如“熟悉”)的解决方案,您可能需要调用外部命令来解析您感兴趣的字符串位:
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
cut -d '-' -f 2 <<<"$filename"
done
这假设bash
您可以cut
循环调用。这比使用 shell 本身内置的操作要慢得多。这里的命令被要求从传递给它的字符串中cut
返回第二个分隔字段(使用“here-string”重定向)。-
bash
答案2
根据你的输出:
ls|awk -F"-" '{print $2}'
应该可以,但是如果你想考虑这t-
部分,那么
ls|grep ^t-|awk -F"-" '{print $2}'
或者
ls|awk -F"t-" '{print $2}'|awk -F"-" '{print $1}'
答案3
当我根据您的示例创建文件列表时,我以ls
这种方式对它们进行排序:
$ ls -1
myFile.c
mySecondFile.c
t-1-myFirstTest.c
t-21-tset241.c
t-3-test1234.c
t-42-my_second_test.c
因此,下面的 bash 函数以相同的顺序输出文件的换行符和数字。
我想删除除换行符以及 t- 和第二个 - 之间的数字之外的所有文本
我对此的解释是,不匹配的文件名t-
应该“删除,换行符除外”,意思是:为这些文件名输出一个空行,但否则输出破折号之间的数字。
lsnums ()
{
for f in *
do
if [[ "$f" =~ t-([[:digit:]]+)- ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
else
echo
fi
done
}
结果输出是:
$ lsnums
1
21
3
42
...其中两个空行对应于以my
而不是开头的第一种类型文件t-
。
答案4
可以简单地通过以下方式完成:
ls | cut -d '-' -f 2