关于shell:如何解析bash中的文件名?

关于shell:如何解析bash中的文件名?

How do you parse a filename in bash?

我的文件名格式如下:

system-source-yyyymmdd.dat

我希望能够使用"-"作为分隔符来解析文件名的不同位。


您可以使用cut命令获取3个``字段''中的每个字段,例如:

1
2
$ echo"system-source-yyyymmdd.dat" | cut -d'-' -f2
source

" -d"指定分隔符,"-f"指定所需字段的编号


仅内置的一种不错且优雅的方法(在我看来:-)是将其放入数组中

1
2
var='system-source-yyyymmdd.dat'
parts=(${var//-/ })

然后,您可以在数组中找到零件。

1
2
3
echo ${parts[0]}  ==> system
echo ${parts[1]}  ==> source
echo ${parts[2]}  ==> yyyymmdd.dat

警告:如果文件名包含空格等"奇怪"字符,或者天堂禁止使用引号,反引号,则此操作将无效。


根据您的需求,awk比cut更灵活。第一个预告片:

1
2
3
4
5
6
7
8
9
10
11
12
13
# echo"system-source-yyyymmdd.dat" \
    |awk -F- '{printf"System: %s
Source: %s
Year: %s
Month: %s
Day: %s
",
              $1,$2,substr($3,1,4),substr($3,5,2),substr($3,7,2)}'

System: system
Source: source
Year: yyyy
Month: mm
Day: dd

问题在于,将awk描述为"更灵活"肯定像是将iPhone称为增强型手机;-)


使用cut命令。

例如

1
echo"system-source-yyyymmdd.dat" | cut -f1 -d'-'

将提取第一位。

更改-f参数的值以获取适当的部分。

这是有关Cut命令的指南。


另一种方法是使用外壳程序的内部解析工具,这避免了创建子进程的开销:

1
2
3
4
5
6
oIFS=$IFS
IFS=-
file="system-source-yyyymmdd.dat"
set $file
IFS=$oIFS
echo"Source is $2"

最简单(也是IMO最佳方法)的方法是使用read

1
2
3
4
5
6
7
$ IFS=-. read system source date ext << EOF
> foo-bar-yyyymmdd.dat
> EOF
$ echo $system
foo
$ echo $source $date $ext
bar yyyymmdd dat

该主题有多种变体,其中许多取决于外壳:

bash$ IFS=-. read system source date ext <<< foo-bar-yyyymmdd.dat

1
2
3
echo"$name" | { IFS=-. read system source date ext
   echo In all shells, the variables are set here...; }
echo but only in some shells do they retain their value here


推荐阅读