bash 在参数中转义冒号、等号、与号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9932798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Escape colons, equals, ampersands in arguments
提问by
Below is my code, which behaves extremely bizarre, and I am not sure I understand the reason, but I think it's somehow connected to path expansion:
下面是我的代码,它的行为非常奇怪,我不确定我是否理解原因,但我认为它以某种方式与路径扩展有关:
EDIT:this is the asxgrabscript mentioned in the second listing:
编辑:这是asxgrab第二个清单中提到的脚本:
#!/usr/bin/env bash
let "i=0"
GET "" | grep 'href="mms://' | while read line
do
echo "$line"
address=`echo $line | grep -Eow '"[^"]+"'`
address_length=$((${#address}-2))
address=${address:1:address_length}
echo "Grabbing '$address', attempt $i, $address_length"
mplayer "'$address' -dumpstream -dumpfile '.wmv' -vf scale\=320\:240" > /dev/null
if [ ! $? ]; then
break 1
fi
let "i++"
done
I've tried dozens of different ways of escaping, quoting and whatnot, and I think I've exhausted my creativity... please help!
我已经尝试了几十种不同的转义、引用等方式,我想我已经耗尽了我的创造力......请帮忙!
Suppose the script is called with these arguments:
假设使用以下参数调用脚本:
./asxgrab 'http://switch3.castup.net/cunet/gm.asp?ai=16&ip=79.180.37.230&course=c20478/2012b&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&ar=c20478_12b_784_01_1&ticket=58353E7A69BF1B9XO655E9E683016C5255C08DD37211ECF495F72A64E5278AA434CSP3C10C028D604AAD6C39FE7D71386D230983BBAF58A2511D14222F95090AE2C4C55CB696B82919A5A8EB44EAF8954DEDB5' 'java.0'
The received response looks like this:
收到的响应如下所示:
<asx version="3.0">
<!-- GMX -->
<param name="encoding" value="utf-8" />
<title>CastUP: c20478_12b_784_01_1</title>
<MOREINFO HREF = "" />
<entry>
<PARAM NAME="EntryType" VALUE="Content" />
<param name="encoding" value="utf-8" />
<PARAM NAME="CastUP_AssociatedURL" VALUE="" />
<PARAM NAME="CastUP_Content_Config" VALUE="" />
<PARAM NAME="CastUP_Content_ClipMediaID" VALUE="9067325" />
<author>openu</author>
<title>CastUP: c20478_12b_784_01_1</title>
<ref href="mms://s3fwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=FE81687B-33CD-4441-A8F6-1DEC9923332C&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183" />
<ref href="...." />
</entry>
When I do this:
当我这样做时:
mplayer "mms://s3fwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=C6527A33-587F-4148-A3D2-E7EDED51316B&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183" -dumpstream -dumpfile java0.wmv -vf scale=320:240
from the terminal, it works, but it doesn't work from the script. Instead it tries to trim the $lineor something like that. I don't even understand what happens, but the output is absolutely of no consequences...
从终端,它工作,但它不从脚本工作。相反,它试图修剪$line或类似的东西。我什至不明白会发生什么,但输出绝对没有任何后果......
This is my uni's site and this is, funny as it gets, a lecture on Java :)
这是我的大学网站,这是一个关于 Java 的讲座,虽然很有趣,但 :)
EDIT:
编辑:
<ref href="mms://s0dwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=111A3770-29DC-40EC-85EC-93453E2819D7&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183" />
Grabbing 'mms://s0dwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=111A3770-29DC-40EC-85EC-93453E2819D7&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183', attempt 0, 268
Can't open joystick device /dev/input/js0: No such file or directory
Can't init input joystick
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
No stream found to handle url 'mms://s0dwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=111A3770-29DC-40EC-85EC-93453E2819D7&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183' -dumpstream -dumpfile 'java.0.wmv' -vf scale=320:240
d324d1043027b0720c295b93e4abb183" />
Grabbing '', attempt 1, -2
Can't open joystick device /dev/input/js0: No such file or directory
Can't init input joystick
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
File not found: ''' -dumpstream -dumpfile 'java.0.wmv' -vf scale=320:240'
Failed to open '' -dumpstream -dumpfile 'java.0.wmv' -vf scale=320:240.
027b0720c295b93e4abb183" />
This is the output I'm getting from the script.
这是我从脚本中得到的输出。
MPlayer SVN-r31918 (C) 2000-2010 MPlayer Team
Can't open joystick device /dev/input/js0: No such file or directory
Can't init input joystick
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
Playing mms://s3fwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=C6527A33-587F-4148-A3D2-E7EDED51316B&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183.
STREAM_ASF, URL: mms://s3fwm.castup.net/server12/16/798/79837168-61.wmv?ct=IL&rg=BZ&aid=16&ts=0&cu=C6527A33-587F-4148-A3D2-E7EDED51316B&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183
Resolving s3fwm.castup.net for AF_INET6...
Couldn't resolve name for AF_INET6: s3fwm.castup.net
Resolving s3fwm.castup.net for AF_INET...
Connecting to server s3fwm.castup.net[212.179.13.65]: 1755...
Connected
file object, packet length = 6100 (6100)
unknown object
unknown object
unknown object
stream object, stream ID: 1
stream object, stream ID: 2
unknown object
data object
mmst packet_length = 6100
Cache size set to 64 KBytes
Stream not seekable!
And this is the expected output.
这是预期的输出。
采纳答案by Adam Liss
Have you tried this?
你试过这个吗?
mplayer "$address" -dumpstream -dumpfile ".wmv" -vf "scale=320:240" > /dev/null
Secrets of bash:
bash的秘密:
- Variables inside double-quotes are expanded; those inside single-quotes are not.
- Words inside quotes are treated as a single token.
- Quotes of one type escape those of the other type.
- 双引号内的变量被扩展;里面的单引号不是。
- 引号内的单词被视为单个标记。
- 一种类型的引用会避开另一种类型的引用。
The original line
原来的线
mplayer "'$address' -dumpstream -dumpfile '.wmv' -vf scale\=320\:240" > /dev/null
called mplayerwith the single argument '$address' -dumpstream -dumpfile '$2.wmv' -vf scale\=320\:240, but mplayerwants each of those tokens to be a separate word.
所谓mplayer与所述单个参数'$address' -dumpstream -dumpfile '$2.wmv' -vf scale\=320\:240,但mplayer希望每个这些令牌的是一个单独的字。
回答by ruakh
If I'm understanding everything correctly, the only real problem I see is that this line:
如果我正确理解一切,我看到的唯一真正的问题是这一行:
mplayer "'$address' -dumpstream -dumpfile '.wmv' -vf scale\=320\:240" > /dev/null
is supposed to be this:
应该是这样的:
mplayer "$address" -dumpstream -dumpfile ".wmv" -vf scale=320:240 > /dev/null
That is, you need to remove the double-quotes that gather all of mplayer's arguments into a single argument, and you need to remove the single-quotes around, and backslashes inside, some of those arguments.
也就是说,您需要删除将 的所有mplayer参数收集到单个参数中的双引号,并且您需要删除其中一些参数周围的单引号和反斜杠。
Other things I might change for cleanliness' sake:
为了清洁我可能会改变的其他事情:
- changing
read linetoread -r linewould eliminate any potential weirdness from backslashes. - a line
line="${line%$'\r'}"at the beginning of thewhile-loop body would lay to rest any concern about stray carriage-returns. - changing
address=`echo $line ...toaddress=`echo "$line" ...would eliminate any risk of word-splitting and filename-expansion and whatnot (not that they seem very likely as it is). - the
[ ! $? ]test is meaningless (since$?is never blank, is it?); changing it to just&& break 1at the end of the previous command would be clearer IMHO, and more effective.
- 更改
read line为read -r line将消除反斜杠中任何潜在的怪异现象。 - -loop 正文
line="${line%$'\r'}"开头的一行while可以消除对杂散回车的任何担忧。 - 更改
address=`echo $line ...为address=`echo "$line" ...将消除分词和文件名扩展等的任何风险(并不是因为它们看起来很有可能)。 - 该
[ ! $? ]测试是没有意义的(因为$?是从来没有空,是吗?);&& break 1恕我直言,将其更改为仅在上一个命令的末尾会更清晰,也更有效。
回答by karatedog
You bash script is very "imperative" as it has been rewritten from Assembly.
您的 bash 脚本非常“重要”,因为它是从 Assembly 中重写的。
Another approach:
另一种方法:
- get the descriptor file
- clean the descriptor file (leave mms://... strings in it)
- use that cleaned result as input for cyclic processing
- 获取描述符文件
- 清理描述符文件(在其中留下 mms://... 字符串)
- 使用清洗后的结果作为循环处理的输入
This was a one liner, I just break it up. You'd put the code between the do..done. I didn't care about the file names being ginormous, I gave them as the output .wmv:
这是一个单衬,我只是把它拆开。你会把代码放在 do..done 之间。我不在乎文件名太大,我把它们作为输出.wmv:
link="http://switch3.castup.net/cunet/gm.asp?ai=16&ip=79.180.37.230&course=c20478/2012b&cuud=user:77f6c69526b9fa05f78d3d6679630308d324d1043027b0720c295b93e4abb183&ar=c20478_12b_784_01_1&ticket=58353E7A69BF1B9XO655E9E683016C5255C08DD37211ECF495F72A64E5278AA434CSP3C10C028D604AAD6C39FE7D71386D230983BBAF58A2511D14222F95090AE2C4C55CB696B82919A5A8EB44EAF8954DEDB5"
for i in $(curl -s "$link" | awk '/mms/ {gsub (/<ref href="/, ""); gsub(/" \/>/, ""); print ##代码##}')
do
mplayer $i -dumpstream -dumpfile $i.wmv -vf scale=320:240
done

