【问题标题】:Escape colons, equals, ampersands in arguments转义参数中的冒号、等号、和号
【发布时间】:2012-04-13 12:54:38
【问题描述】:

下面是我的代码,它的行为非常奇怪,我不确定我是否理解原因,但我认为它与路径扩展有关:

编辑:这是第二个清单中提到的asxgrab 脚本:

#!/usr/bin/env bash

let "i=0"

GET "$1" | 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 '$2.wmv' -vf scale\=320\:240" > /dev/null
    if [ ! $? ]; then
        break 1
    fi
    let "i++"
done

我尝试了几十种不同的转义、引用和诸如此类的方式,我想我已经耗尽了我的创造力......请帮忙!

假设使用这些参数调用脚本:

./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'

收到的响应如下所示:

<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>

当我这样做时:

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

从终端,它可以工作,但它不能从脚本工作。相反,它会尝试修剪$line 或类似的东西。我什至不明白会发生什么,但输出绝对没有任何后果......

这是我大学的网站,这很有趣,是关于 Java 的讲座 :)

编辑:

<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" />

这是我从脚本中得到的输出。

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!

这是预期的输出。

【问题讨论】:

  • 你没有说出它应该做什么:-) 我能够破译你读了一个文件(./asxgrab 做了什么)然后你把那个文本文件扔到你的脚本中用href="mms:// greps 行,然后遍历匹配的行。
  • echo "$line" 和 echo "Grabbing '$address', attempt $i, $address_length" 命令打印出您期望的结果吗?
  • 好的,但据我了解,问题是如何从 asx 文件中正确提取视频 URL,您想将其扔给 mplayer(正如您所写,它可以在终端上工作,但不能从脚本)
  • 当我运行你的脚本时,$line 似乎附加了一个'\r'(或者,如果你愿意,一个 CTRL-M)。这相关吗?

标签: bash command-line escaping quotes


【解决方案1】:

你试过了吗?

mplayer "$address" -dumpstream -dumpfile "$2.wmv" -vf "scale=320:240" > /dev/null

bash 的秘密:

  • 双引号内的变量被扩展;单引号内的不是。
  • 引号内的单词被视为单个标记。
  • 一种类型的引用会避开另一种类型的引用。

原行

mplayer "'$address' -dumpstream -dumpfile '$2.wmv' -vf scale\=320\:240" > /dev/null

使用单个参数 '$address' -dumpstream -dumpfile '$2.wmv' -vf scale\=320\:240 调用 mplayer,但 mplayer 希望这些标记中的每一个都是一个单独的词。

【讨论】:

  • @wvxvw:但是scale=320:240周围的引号没有作用;一定还有其他你之前错过的东西。 :-/
  • 另一个关于 GREP 的:grep 是一个行工具,这意味着如果你有一个 2 TB 的文件并且你 grep 它,你会立即得到匹配,如果有的话,你不要'不必等待整个文件被处理。这意味着 grep 将一次返回 1 行,因此 while read line 块是不必要的(因为它将处理单行文本输入)。
  • @wvxvw:你现在有一个工作脚本,对吧?好吧,尝试将"scale=320:240" 改回scale=320:240(如我的回答),您会发现它仍然有效。您一定同时更改了其他内容。
【解决方案2】:

如果我理解正确,我看到的唯一真正的问题是这一行:

    mplayer "'$address' -dumpstream -dumpfile '$2.wmv' -vf scale\=320\:240" > /dev/null

应该是这样的:

    mplayer "$address" -dumpstream -dumpfile "$2.wmv" -vf scale=320:240 > /dev/null

也就是说,您需要删除将mplayer 的所有参数集中到一个参数中的双引号,并且您需要删除其中一些参数周围的单引号和反斜杠。

为了清洁,我可能会更改其他内容:

  • 将 read line 更改为 read -r line 将消除反斜杠的任何潜在怪异现象。
  • line="${line%$'\r'}" 位于 while-loop 主体开头的一行 line="${line%$'\r'}" 可以消除对杂散回车的任何担忧。
  • 将address=`echo $line ... 更改为address=`echo "$line" ... 将消除任何单词拆分和文件名扩展等风险(并不是说它们看起来很有可能)。
  • [ ! $? ] 测试毫无意义(因为$? 永远不会为空,是吗?);在上一个命令的末尾将其更改为 &amp;&amp; break 1 会更清晰,更有效。

【讨论】:

  • @wvxvw:不,[ ! ... ] 不是这样工作的。尝试if [ ! ... ] ; then echo foo ; else echo bar ; fi 获取... 的各种值,例如0 和1。你会发现它总是打印bar。它会打印foo 的唯一时间是... 为空白(空字符串);例如,if [ ! '' ] ; then echo foo ; fi 将打印 foo。
  • @wvxvw:Bash 以几种不同的方式表示布尔值。 . .实际上,这很复杂。通常,命令应该以指示它是否成功的退出状态结束:0 表示成功,非零表示错误。布尔值使用“成功”为“真”,“错误”为“假”,所以如果foo 返回0 ("success/true") 和bar 如果foo 返回非零(“错误/假”)。 (这种逻辑被if、while、&amp;&amp;、||、!等使用)[续]
  • @wvxvw: [continued] 因此,相反地,有许多命令真正设计用于if 等等,它们返回“成功” 当他们的意思是“真”时,“错误” 当他们的意思是“假”时。例如,如果 $a 是 a,[ "$a" = a ] 将返回 0 ("success/true"),否则返回非零值 ("error/false")。所以这一切都很好地结合在一起,手握手套。到目前为止你和我在一起吗?但是请注意[ ]的基本测试,如果你不指定任何其他测试,它只是检查它是否有一个非空参数;而! 则否定了这一点。 [继续]
  • @wvxvw: [continued] 因此,使用0 作为“真”退出状态不应被视为意味着[ 1 ] 是“假”;相反,[ 0 ] 和 [ 1 ] 都返回 0(“true”),[ ! 0 ] 和 [ ! 1 ] 都返回非零值(“false”),因为 0 和 1 都不是-空白的。相比之下,[ ] 和 [ '' ] 都是 false,[ ! ] 和 [ ! '' ] 都是 true。到目前为止,一切都很好?现在,它开始变得复杂的地方是算术表达式。在算术表达式中,0 表示“假”,非零值表示“真”——这是 C 的遗产——所以 [续]
  • @wvxvw: [continued] echo $(( 0 == 0 )) 将打印 1 ("true") 和 echo $(( 0 ? 1 : 2 )) 将打印 2 (因为 0 表示 "错误的”)。 for (( i = 0; 1 ; i++ )) ; do ... ; done 将永远循环,而 for (( i = 0; 0 ; i++ )) ; do ... ; done 将什么也不做。所以有几个不同的“真”和“假”概念,这取决于你在 Bash 中的位置,其中一些与另一些相反。但这还不是最糟糕的:Bash 实际上会在它们之间进行转换。 let 0 或 (( 0 )) 将具有非零退出状态(“错误/假”),因为 0 为假 [继续]
【解决方案3】:

你的 bash 脚本非常“必要”,因为它是从 Assembly 重写的。

另一种方法:

  • 获取描述符文件
  • 清理描述符文件(保留 mms://... 字符串)
  • 将清理后的结果用作循环处理的输入

这是一个单一的班轮,我只是把它拆开。你会把代码放在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 $0}')
do
  mplayer $i -dumpstream -dumpfile $i.wmv -vf scale=320:240
done

【讨论】:

    猜你喜欢
    • 2011-11-20
    • 2022-06-29
    • 1970-01-01
    • 2012-09-25
    • 2013-01-30
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多