如何处理“--”在 shell 脚本参数中?
这个问题有 3 个部分,每个部分都很简单,但组合在一起并不简单(至少对我来说):)
需要编写一个脚本,应将其参数作为其参数:
- 另一个命令的一个名称
- 文件命令
- 列表的
几个参数举例:
./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
当文件名
包含空格
和/或“--”时,此解决方案将失败,例如
/some--path/to/more/idiotic file name.txt
问题2:如何正确获取$command
其$args
和$filenames
用于稍后执行?
问题3: - 如何实现以下执行风格?
echo $filenames | $command $args #but want one filename = one line (like ls -1)
这是很好的 shell 解决方案,还是需要使用例如 perl?
This question has 3 parts, and each alone is easy, but combined together is not trivial (at least for me) :)
Need write a script what should take as its arguments:
- one name of another command
- several arguments for the command
- list of files
Examples:
./my_script head -100 a.txt b.txt ./xxx/*.txt
./my_script sed -n 's/xxx/aaa/' *.txt
and so on.
Inside my script for some reason I need distinguish
- what is the command
- what are the arguments for the command
- what are the files
so probably the most standard way write the above examples is:
./my_script head -100 -- a.txt b.txt ./xxx/*.txt
./my_script sed -n 's/xxx/aaa/' -- *.txt
Question1: Is here any better solution?
Processing in ./my_script (first attempt):
command="$1";shift
args=`echo $* | sed 's/--.*//'`
filenames=`echo $* | sed 's/.*--//'`
#... some additional processing ...
"$command" "$args" $filenames #execute the command with args and files
This solution will fail when the filenames
will contain spaces
and/or '--', e.g.
/some--path/to/more/idiotic file name.txt
Question2: How properly get $command
its $args
and $filenames
for the later execution?
Question3: - how to achieve the following style of execution?
echo $filenames | $command $args #but want one filename = one line (like ls -1)
Is here nice shell solution, or need to use for example perl?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,听起来您正在尝试编写一个脚本,该脚本接受命令和文件名列表,并依次对每个文件名运行该命令。这可以在 bash 中用一行完成:
但是,也许我误解了您的意图,所以让我单独回答您的问题。
与使用“--”(它已经具有不同的含义)不同,以下语法对我来说感觉更自然:
要在 bash 中提取参数,请使用 getopts:
如果您想运行命令其余每个参数,它看起来像这样:
如果您想从 STDIN 读取文件名,它看起来更像这样:
First of all, it sounds like you're trying to write a script that takes a command and a list of filenames and runs the command on each filename in turn. This can be done in one line in bash:
However, maybe I've misinterpreted your intent so let me answer your questions individually.
Instead of using "--" (which already has a different meaning), the following syntax feels more natural to me:
To extract the arguments in bash, use
getopts
:If you want to run a command for each of the remaining arguments, it would look like this:
If you want to read the filenames from STDIN, it would look more like this:
$@
变量在引用时将能够按应有的方式对参数进行分组:如果给出:
将打印
现在,您所要做的就是解析循环。您可以使用一些非常简单的规则:
您可以使用以下命令检查参数中的第一个字符是否为破折号:
如果您以前没有见过此语法,那么它是一个左过滤器。
#
将变量名称的两部分分开。第一部分是变量的名称,第二部分是要截断的glob过滤器(不是正则表达式)。在本例中,它是一个破折号。只要这个说法不正确,你就知道你有一个参数。顺便说一句,在这种情况下可能需要也可能不需要x
。当您运行测试时,如果有一个带有破折号的字符串,测试可能会将其误认为是测试的参数而不是值。把它放在一起会是这样的:
The
$@
variable, when quoted will be able to group parameters as they should be:If given:
Will print
Now, all you have to do is parse the loop out. You can use some very simple rules:
You can check to see if the first character in the parameter is a dash by using this:
If you haven't seen this syntax before, it's a left filter. The
#
divides the two parts of the variable name. The first part is the name of the variable, and the second is the glob filter (not regular expression) to cut off. In this case, it's a single dash. As long as this statement isn't true, you know you have a parameter. BTW, thex
may or may not be needed in this case. When you run a test, and you have a string with a dash in it, the test might mistake it for a parameter of the test and not the value.Put it together would be something like this:
问题 1
我不这么认为,至少如果您需要对任意命令执行此操作,则不会。
问题 3
问题 2
这与问题 3 有什么不同?
Question 1
I don't think so, at least not if you need to do this for arbitrary commands.
Question 3
Question 2
How does that differ from question 3?