共计 2477 个字符,预计需要花费 7 分钟才能阅读完成。
本文首发于集体博客 http://zuyunfei.com/2016/03/2…,欢送浏览最新内容!
截取文件名和后缀
编写 Shell 脚本的过程中,常常会和文件名和文件门路打交道。如果用户输出了一个文件的全名(可能蕴含绝对路径和文件后缀),如何失去文件的路径名,文件名,文件后缀这些信息呢。Shell 脚本领有弱小的字符串解决能力,如果把文件名当做字符串,咱们不难应用 cut 或 sed 这样的工具失去咱们想要的后果。
$fullfile=/the/path/foo.txt
$fullname=$(basename $fullfile)
$dir=$(dirname $fullfile)
$filename=$(echo $fullname | cut -d . -f1)
$extension=$(echo $fullname | cut -d . -f2)
$ echo $dir , $fullname , $filename , $extension
/the/path , foo.txt , foo , txt
这里应用 basename 命令能够间接失去蕴含后缀的文件名,而 dirname 命令能够失去路径名,而后就能简略的用 cut 截取文件名和后缀名。
更简单的状况
如果凑合简略利用场景,到这里曾经能够打完出工了,然而有时候文件可能不止有一个后缀,比方 *.tar.gz,怎么失去最初一个后缀呢?再 cut 一回?当然能够,然而如果文件名是 mylib.1.0.1a.zip 这样的呢?呃 …… 正则表达式必定能够。
$ fullname=mylib.1.0.1a.zip
$ filename=$(echo $fullname | sed 's/\.[^.]*$//')
$ extension=$(echo $fullname | sed 's/^.*\.//')
$ echo $filename, $extension
mylib.1.0.1a, zip
这外面的逻辑是这样的:
- 文件名:把以
.
字符结尾当前始终到行尾都是非.
字符的子串替换为空。 - 后缀名:把从行首开始以
.
字符结尾的子串替换为空。
光用语言把这两个正则表达式形容进去脑细胞也要死不少。有没有像下面 cut 版本一样简略容易了解的办法呢?因为 .
分隔符的个数不确定,失常应用 cut 来宰割最初一个 .
字符是不太可能的。然而咱们可应用 rev 命令将字符串反转一下,辨别后缀和文件名的 .
字符地位就确定了。截取了想要的局部之后,再次反转就失去了咱们想要的内容。
$ fullname=mylib.1.0.1a.zip
$ filename=$(rev <<< $fullname | cut -d . -f2- | rev)
$ extension=$(rev <<< $fullname | cut -d . -f1 | rev)
$ echo $filename, $extension
mylib.1.0.1a, zip
应用参数扩大
其实不借助简单的正则表达式,甚至不调用 basename, dirname, cut, sed 命令,shell 脚本一样能够做到所有的操作。看上面的实现:
$ fullfile=/the/path/mylib.1.0.1a.zip
$ fullname="${fullfile##*/}"
$ dir="${fullfile%/*}"
$ extension="${fullname##*.}"
$ filename="${fullname%.*}"
$ echo $dir , $fullname , $filename , $extension
/the/path , mylib.1.0.1a.zip , mylib.1.0.1a , zip
真是不能再简洁了,大括号之内变量名配合几个神奇的字符,就是 Shell 的参数扩大 (Parameter Extension) 性能。
-
${fullfile##*/}
:从后面开始删除 fullfile 中最大匹配(longest matching pattern)*/
的字符串 -
${fullfile%/*}
:从前面开始删除 fullfile 中最小匹配(shortest matching pattern)/*
的字符串 -
${fullname##*.}
:从后面开始删除 fullname 中最大匹配(longest matching pattern)*.
的字符串 -
${fullname%.*}
:从前面开始删除 fullname 中最小匹配(shortest matching pattern).*
的字符串
参数扩大有多种形式,在 shell 编程中能够用作参数的拼接,字符串的替换,参数列表截取,变量初值等操作,这里不再详述,请参考前面的性能列表和官网文档
参数扩大性能列表
参数模式 | 扩大后 |
---|---|
x{y,z} | xy xz |
${x}{y, z} | ${x}y ${x}z |
${x}{y, $z} | ${x}y ${x}${z} |
${param#pattern} | 从 param 后面删除 pattern 的最小匹配 |
${param##pattern} | 从 param 后面删除 pattern 的最大匹配 |
${param%pattern} | 从 param 前面删除 pattern 的最小匹配 |
${param%%pattern} | 从 param 前面删除 pattern 的最大匹配 |
${param/pattern/string} | 从 param 中用 string 替换 pattern 的第一次匹配,string 可为空 |
${param//pattern/string} | 从 param 中用 string 替换 pattern 的所有匹配,string 可为空 |
${param:3:2} | 截取 $param 中索引 3 开始的 2 个字符 |
${param:3} | 截取 $param 中索引 3 至开端的字符 |
${@:3:2} | 截取参数列表 $@中第 3 个开始的 2 个参数 |
${param:-word} | 若 $param 为空或未设置,则参数式返回 word,$param 不变 |
${param:+word} | 若 $param 为非空,则参数式返回 word,$param 不变 |
${param:=word} | 若 $param 为空或为设置,则参数式返回 word,同时 $param 设置为 word |
${param:?message} | 若 $param 为空或为设置,则输入错误信息 message,若蕴含空白符,则需引号 |