从bash中运行程序,无法正确转移空间

时间:2015-10-03 12:08:41

标签: macos bash mdns dns-sd

我正在Mac OSX 10.11上编写一个bash脚本,自动使用dns-sd“代理”我的Bonjour广告,用于AFP,SMB&我连接到VPN时有些打印机。

我的脚本的基本要点是我在调用dns-sd时声明了一些数组以供以后使用。阵列我很难成为:

SERVICE_TEXTS=(
''
''
model=TimeCapsule8,119
model=Xserve
'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F'
'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty="Brother MFC-9120CN" product="(Brother MFC-9120CN)" adminurl=http://BRN001BA9243652.local./ priority=75 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F'
'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp ty="Brother MFC-9120CN" product="(Brother MFC-9120CN)" adminurl=http://BRN001BA9243652.local./ priority=25 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=F TBCP=T'
)

为了确定我是否需要实际运行dns-sd,我这样做:

ifconfig ppp0 &>/dev/null

使用以下命令测试ifconfig的返回值:

if [ "$?" -eq "0" ]; then...

如果存在ppp0,我遍历我的数组的长度,检查dns-sd当前是否正在运行,依此类推。

如果dns-sd实例一直在运行,但ppp0现在不可用,我会通过PID保存它们,并在几分钟内再次检查。

我确信我的其余代码正在执行我想要的内容,所以我会直接跳到违规行,希望大致的想法足够明确。

dns-sd -P "${SERVICE_NAMES[$n]}" "${SERVICE_TYPES[$n]}" local ${SERVICE_PORTS[$n]} "${SERVICE_NAMES[$n]}.local" "${SERVICE_IPS[$n]}" ${SERVICE_TEXTS[$n]} &>/dev/null &

为清楚起见,dns-sd的手册页显示这是-P的用法。

dns-sd -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...]              (Proxy)

我面临的问题是最后三个SERVICE_TEXTS元素中空格字符的行为。到目前为止的故障排除是在终端做所有事情,以确保我不会错过一些非常明显/疯狂的东西。这正是我输入的内容以及返回的内容......哪个有效

$ dns-sd -P "Brother MFC-9129CN" _ipp._tcp local 631 "Brother MFC-9120CN.local" 192.168.1.2 txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother\ MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F

Registering Service Brother MFC-9129CN._ipp._tcp.local host Brother MFC-9120CN.local port 631 TXT txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother\ MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F
DATE: ---Sat 03 Oct 2015---
21:11:40.927  ...STARTING...
21:11:41.818  Got a reply for record Brother MFC-9120CN.local: Name now registered and active
21:11:41.818  Got a reply for service Brother MFC-9129CN._ipp._tcp.local.: Name now registered and active

当我在命令中使用变量时(为清晰起见,回声)......发生这种情况

$ echo ${SERVICE_TEXTS[4]}
txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F

$ dns-sd -P "Brother MFC-9129CN" _ipp._tcp local 631 "Brother MFC-9120CN.local" 192.168.1.2  ${SERVICE_TEXTS[4]}

Registering Service Brother MFC-9129CN._ipp._tcp.local host Brother MFC-9120CN.local port 631 TXT txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\\\\ MFC-9120CN product=\(Brother MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F
DATE: ---Sat 03 Oct 2015---
21:18:56.968  ...STARTING...
21:18:57.842  Got a reply for record Brother MFC-9120CN.local: Name now registered and active
21:18:57.842  Got a reply for service Brother MFC-9129CN._ipp._tcp.local.: Name now registered and active

问题是元素4的部分

"...ty=Brother\ MFC..."

dns-sd报告此为

"...ty=Brother\\\\ MFC..."

当我只是输入字符串而不是使用变量时,你会注意到,dns-sd用一个“\”报告它。

显然四个“\”对我没有任何好处...如果我删除“\”,我仍然无法获得所需的结果,因为dns-sd认为我正在描述一个新密钥。我输入

"\\"

尝试获取文字“\”并从内存中获取dns-sd仍然会收到四个。

我还玩过单引号和双引号,包括用双引号调用dns-sd中的变量,但是在每个空格中添加了反斜杠。这使得dns-sd将TXT字符串视为具有一个值的一个键,其中值包含空格。这比没有引号的调用要少得多,所以我放弃了进一步调查。

所以基本上,似乎dns-sd没有收到或者只有四个“\”......它只需要一个然后一切都会完美运行......

调用dns-sd并在没有引号的情况下传递$ {SERVICE_TEXTS [$ n]}非常接近所需的行为,但无法处理键值对的“值”中的空格字符。

这里的任何指导都将非常感谢!我一直在倾注bash手册,搜索堆栈交换并尝试我能想到的所有内容,让这项工作现在进行4小时:(

1 个答案:

答案 0 :(得分:1)

因此,在博主的帮助下,我获得了这个脚本的灵感,问题就解决了。

这确实是一个引用问题,因此我认为它看似无穷无尽的实验,导致不同程度的成功。

像建议的住所一样,dnd-sd收到类似"key=value key=value with spaces"而非key=value key="value with spaces" key=valueWithoutSpaces

的案例

我遇到的问题是难以看到将在我的脚本中执行的EXACT命令,因为dns-sd似乎也在进行一些转义。从这里开始,确定将我的工作重点放在引用上的确切位置要容易得多。

所以要检查一下,有人建议我使用这样的东西

#FIX: by using a temporary variable we can debug the exact command that will be used including all quotes
CMD="dns-sd -P \"${SERVICE_NAMES[$n]}\" ${SERVICE_TYPES[$n]} local ${SERVICE_PORTS[$n]} \"${SERVICE_NAMES[$n]}.local\" \"${SERVICE_IPS[$n]}\" ${SERVICE_TEXTS[$n]} &>/dev/null &"
echo "DEBUG: $CMD"

# use exactly this command 
eval $CMD
PIDS[$n]=$!;

生成的SERVICE_TEXTS [4]键

'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty="Brother MFC-9120CN" product="(Brother MFC-9120CN)" adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F'

根据你使用的逃逸空间的机制,dns-sd期望转义括号没有帮助;如果您输入\[space]来逃避value with spaces,那么它也希望您转义括号。但引用整个事情会导致dns-sd处理括号本身......

因此,我将从中获取的信息是创建一个临时变量来显示变量扩展,在评估它之前回应它以指导搜索不稳定的引号。