【发布时间】:2012-01-29 21:38:46
【问题描述】:
我正在编写一个快速的 shell 脚本来一举构建和执行我的程序。
我已经把那部分记下来了,但我想包含一些 if/else 来捕捉不好的扩展 - 如果它不是 .adb(它是一个 Ada 脚本),它不会让其余的程序执行。
我的问题分为两部分:
- 如何只获取扩展名?还是说
*.adb更容易? - if/else 语句是什么样的?我在 Bash 方面的经验有限,所以我知道这是一个非常糟糕的问题。
谢谢!
【问题讨论】:
我正在编写一个快速的 shell 脚本来一举构建和执行我的程序。
我已经把那部分记下来了,但我想包含一些 if/else 来捕捉不好的扩展 - 如果它不是 .adb(它是一个 Ada 脚本),它不会让其余的程序执行。
我的问题分为两部分:
*.adb 更容易?谢谢!
【问题讨论】:
有一些方法可以提取扩展名,但您实际上并不需要:
if [[ $filename == *.adb ]] ; then
. . . # this code is run if $filename ends in .adb
else
. . . # this code is run otherwise
fi
(提取扩展名的麻烦在于你必须定义你所说的“扩展名”。一个名为foo的文件的扩展名是什么?一个名为report.2012.01.29的文件怎么样?所以一般-目的扩展提取代码很棘手,如果您的目标只是确认该文件具有特定扩展名,则不值得。)
【讨论】:
有多种方法可以做到这一点。哪个最好部分取决于后续操作。
给定一个变量$file,您可能想要测试扩展名是什么。在这种情况下,您可能会做得最好:
extn=${file##*.}
这将删除名称中最后一个点之前的所有内容、斜线和所有内容,如果文件名是 adafile.adb,则留下 adb。
另一方面,如果你想根据扩展做不同的事情,你可以使用:
case "$file" in
(*.adb) ...do things with .adb files;;
(*.pqr) ...do things with .pqr files;;
(*) ...cover the rest - maybe an error;;
esac
如果您想要不带扩展名的名称,您可以使用更传统的方式:
base=$(basename $file .adb)
path=$(dirname $file)
basename 命令为您提供文件名的最后一个组成部分,去掉了扩展名 .adb。 dirname 命令为您提供指向文件名最后一个组成部分的路径,如果没有指定路径,则默认为 .(当前目录)。
最近执行这两个操作的方法是:
base=${file##/}
path=${file%/*}
这些的优点是它们是内置操作,不会调用单独的可执行文件,因此它们更快。内置函数的缺点是,如果您的名称以斜杠结尾,则内置函数会将其视为重要,但命令不会(并且该命令可能会为您提供更理想的行为,除非您想要争论 GIGO)。
还有其他可用的技术。 expr 命令是一种旧的、相当重量级的机制,通常不会使用(但它非常标准)。可能还有其他技术使用(( ... ))、$(( ... )) 和[[ ... ]] 运算符来评估各种表达式。
【讨论】:
${file##*.},因为如果文件名没有句点,它会表现得很糟糕。更糟糕的是,如果它的父目录带有句点,而文件名没有(例如 file="/parentdir/dir.d/subdir/filename" -> extn="d/subdir/filename")。
要仅从文件路径和名称中获取扩展名,请使用参数扩展:
${filename##*.} # deletes everything to the last dot
要将它与字符串 adb 进行比较,只需这样做
if [[ ${filename##*.} != adb ]] ; then
echo Invalid extension at "$filename".
exit 1
fi
或者,使用“else”:
if [[ ${filename##*.} != adb ]] ; then
echo Invalid extension at "$filename".
else
# Run the script...
fi
【讨论】:
扩展名:
fileext=`echo $filename | sed 's_.*\.__'`
测试
if [[ x"${fileext}" = "xadb" ]] ; then
#do something
fi
【讨论】: