我目前有以下代码行:
ls /some/dir/prefix* | sed -e 's/prefix.//' | tr 'n' ' '
这确实实现了我想要它做的事情:
- 获取以前缀开头的文件列表
- 从每个字符串中删除路径和前缀
- 删除换行符并替换为空格以供以后处理。
例如:
/some/dir/prefix.hello
/some/dir/prefix.world
应该成为
hello world
但我觉得有一个更好的方法可以做到这一点。有没有更好的方法可以在一行中做到这一点?
这是一个仅使用内置的两行代码:
fnames=(some/dir/prefix*)
echo "${fnames[@]##*.}"
这是它的工作原理:
fnames=(some/dir/prefix*)
创建一个数组,其中包含所有以prefix
开头的文件,并避免了解析ls
带来的所有问题echo "${fnames[@]##*.}"
是两个参数扩展的组合:${fnames[@]}
打印所有数组元素,##*.
部分从每个数组元素中删除以.
结尾的任何内容的最长匹配项,只留下扩展名
如果您执着于单行,只需将两个命令与&&
连接即可。
不建议将ls
输出传递给外部程序,以下bash解决方案可能会在这里为您提供帮助。
for file in prefix*; do echo ${file##*.}; done
现在也添加一个非一个衬里形式的解决方案。
for file in prefix*
do
echo ${file##*.}
done
这是一个非常简单的 Awk 单行来实现这一点:
awk -F. '{$0=FILENAME; printf $NF" "; nextfile}' /some/dir/prefix*
它基本上执行以下操作:
-F.
:将字段分隔符FS
设置为.
。这样$NF
表示扩展。$0=FILENAME
:忽略当前记录并将其设置为FILENAME
,以这种方式重新解析所有内容。print $NF; nextfile
:打印扩展名并转到下一个文件。
这样做的问题是文件仍然读取当前文件的记录。如果该文件为空,这将失败。
若要使用空文件执行此操作,可以使用gawk
扩展名BEGINFILE
awk -F. 'BEGINFILE{$0=FILENAME; printf $NF" "; nextfile}' /some/dir/prefix*
或者你可以遍历所有参数:
awk -F. 'BEGIN{for(i in ARGV){$0=ARGV[i]; printf $NF" "};exit}' /some/dir/prefix*
一种使用 awk 的方法:
ls /some/dir/prefix* | awk -F"." '{printf "%s ", $2} END {print ""}'
它可能有资格"更好",因为只有一个命令输出是通过管道传输的?!