[英]How to handle “--” in the shell script arguments?
这个问题有 3 个部分,每个部分都很简单,但结合在一起并不是微不足道的(至少对我来说):)
需要编写一个脚本,它的 arguments 应该是什么:
例子:
./my_script head -100 a.txt b.txt ./xxx/*.txt
./my_script sed -n 's/xxx/aaa/' *.txt
等等。
由于某种原因在我的脚本中我需要区分
所以可能最标准的方式写上面的例子是:
./my_script head -100 -- a.txt b.txt ./xxx/*.txt
./my_script sed -n 's/xxx/aaa/' -- *.txt
问题1:这里有更好的解决方案吗?
在 ./my_script 中处理(第一次尝试):
command="$1";shift
args=`echo $* | sed 's/--.*//'`
filenames=`echo $* | sed 's/.*--//'`
#... some additional processing ...
"$command" "$args" $filenames #execute the command with args and files
当filenames
包含spaces
和/或“--”时,此解决方案将失败,例如
/some--path/to/more/白痴文件名.txt
问题2:如何正确获取$command
的$args
和$filenames
以供以后执行?
Question3: - 如何实现下面的执行风格?
echo $filenames | $command $args #but want one filename = one line (like ls -1)
这里是不错的 shell 解决方案,还是需要使用例如 perl?
首先,听起来您正在尝试编写一个脚本,该脚本接受一个命令和一个文件名列表,并依次对每个文件名运行该命令。 这可以在 bash 中的一行中完成:
$ for file in a.txt b.txt ./xxx/*.txt;do head -100 "$file";done $ for file in *.txt; do sed -n 's/xxx/aaa/' "$file";done
但是,也许我误解了您的意图,所以让我单独回答您的问题。
而不是使用“--”(已经有不同的含义),下面的语法对我来说更自然:
./my_script -c "head -100" a.txt b.txt ./xxx/*.txt ./my_script -c "sed -n 's/xxx/aaa/'" *.txt
要提取 bash 中的 arguments,请使用getopts
:
SCRIPT=$0
while getopts "c:" opt; do
case $opt in
c)
command=$OPTARG
;;
esac
done
shift $((OPTIND-1))
if [ -z "$command" ] || [ -z "$*" ]; then
echo "Usage: $SCRIPT -c <command> file [file..]"
exit
fi
如果您想为剩余的每个 arguments 运行一个命令,它看起来像这样:
for target in "$@";do
eval $command \"$target\"
done
如果你想从 STDIN 读取文件名,它看起来更像这样:
while read target; do
eval $command \"$target\"
done
$@
变量,当被引用时将能够对参数进行分组,因为它们应该是:
for parameter in "$@"
do
echo "The parameter is '$parameter'"
done
如果给出:
head -100 test this "File name" out
将打印
the parameter is 'head'
the parameter is '-100'
the parameter is 'test'
the parameter is 'this'
the parameter is 'File name'
the parameter is 'out'
现在,您所要做的就是解析循环。 您可以使用一些非常简单的规则:
您可以使用以下方法检查参数中的第一个字符是否为破折号:
if [[ "x${parameter}" == "x${parameter#-}" ]]
如果您以前没有见过这种语法,那它就是一个左过滤器。 #
分隔变量名的两部分。 第一部分是变量名,第二部分是要截断的glob过滤器(不是正则表达式)。 在这种情况下,它是一个破折号。 只要这个陈述不正确,你就知道你有一个参数。 顺便说一句,在这种情况下可能需要也可能不需要x
。 当你运行一个测试并且你有一个带有破折号的字符串时,测试可能会将它误认为是测试的参数而不是值。
放在一起会是这样的:
parameterFlag=""
for parameter in "$@" #Quotes are important!
do
if [[ "x${parameter}" == "x${parameter#-}" ]]
then
parameterFlag="Tripped!"
fi
if [[ "x${parameter}" == "x--" ]]
then
print "Parameter \"$parameter\" ends the parameter list"
parameterFlag="TRIPPED!"
fi
if [ -n $parameterFlag ]
then
print "\"$parameter\" is a file"
else
echo "The parameter \"$parameter\" is a parameter"
fi
done
问题 1
我不这么认为,至少如果您需要对任意命令执行此操作。
问题 3
command=$1
shift
while [ $1 != '--' ]; do
args="$args $1"
shift
done
shift
while [ -n "$1" ]; do
echo "$1"
shift
done | $command $args
问题2
这与问题 3 有何不同?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.