我有一个命令,它返回由引号括起的网络接口列表: -
networksetup -listnetworkserviceorder | grep "Hardware Port" | grep -v "Wi-Fi" | sed 's#([^:]*:\ \([^,]*\),.*#\"\1\"#'
现在我需要将其转换为另一个命令的参数: -
networksetup -ordernetworkservices "Wi-Fi" <the other interfaces>.
我试过
services=`networksetup -listnetworkserviceorder | grep "Hardware Port" | grep -v "Wi-Fi" | sed 's#([^:]*:\ \([^,]*\),.*#\"\1\"#' | paste -sd " " -`
# set order after above
networksetup -ordernetworkservices Wi-Fi $services
但那是失败的。似乎我的报价被剥夺了,但我无法弄清楚原因。
echo $services
给了我
"Dell Universal Dock D6000" "USB 10/100/1000 LAN" "Bluetooth PAN" "Thunderbolt Bridge"
我还尝试使用单引号和双引号包围的变量进行上述操作。
该命令将吐出到shell:
"Dell Universal Dock D6000"
"USB 10/100/1000 LAN"
"Bluetooth PAN"
"Thunderbolt Bridge"
我最终需要的是:
networksetup -ordernetworkservices Wi-Fi "Dell Universal Dock D600" "USB 10/100/1000 LAN" "Bluetooth PAN" "Thunderbolt Bridge"
我知道答案就在我面前,但是我错过了。
答案 0 :(得分:2)
如果没有这样的网络设置程序,很难说清楚。但是看看:
mock () {
echo '"Dell Universal Dock D6000"
"USB 10/100/1000 LAN"
"Bluetooth PAN"
"Thunderbolt Bridge"'
}
mock
"Dell Universal Dock D6000"
"USB 10/100/1000 LAN"
"Bluetooth PAN"
"Thunderbolt Bridge"
echo $(mock)
"Dell Universal Dock D6000" "USB 10/100/1000 LAN" "Bluetooth PAN" "Thunderbolt Bridge"
echo "$(mock)"
"Dell Universal Dock D6000"
"USB 10/100/1000 LAN"
"Bluetooth PAN"
"Thunderbolt Bridge"
和
for s in $(echo "$(mock)"); do echo "<"$s">"; done
<"Dell>
<Universal>
<Dock>
<D6000">
<"USB>
<10/100/1000>
<LAN">
<"Bluetooth>
<PAN">
<"Thunderbolt>
<Bridge">
for s in "$(echo "$(mock)")"; do echo "<"$s">"; done
<"Dell Universal Dock D6000" "USB 10/100/1000 LAN" "Bluetooth PAN" "Thunderbolt Bridge">
答案 1 :(得分:2)
首先:在shell中,您应该将引号视为围绕数据的内容,而不是数据中的内容。您在数据中嵌入了引号,并期望它们像数据一样工作,并且它不会以这种方式工作。更具体地说,shell在替换变量值之前解析引号(以及转义和其他一些东西),所以如果你在变量的值中有引号,那么当它被替换到命令行时它会&# 39;为了达到预期的效果为时已晚。
那么,如果每个端口名称可能包含空格,您将如何将其保存为单独的项目?在bash中,您可以将它们存储在一个数组中,并使用"${arrayname[@]}"
扩展数组 - 双引号和[@]
的组合使bash将每个数组元素视为一个单独的单词,基本上就像每个项目被单独引用。
那么如何将networksetup
的输出转换为数组呢?好吧,如果你有bash版本4,你可以使用readarray
,但macOS只附带bash v3。你仍然可以做到这一点,它只是一点点工作。您有一个read
循环读取networksetup
的每一行输出,经过处理以删除除服务名称之外的所有内容(并且不添加引号)。但是你不能让循环成为管道的一部分,或者它将在子shell中运行,并且数据在退出时会丢失,因此你必须重定向循环的输入。命令用< <( )
替换。像这样:
service_list=()
while read service; do
service_list+=("$service") # Note: double-quotes and parens are both needed
done < <(networksetup -listnetworkserviceorder | grep "Hardware Port" | grep -v "Wi-Fi" | sed 's#([^:]*:\ \([^,]*\),.*#\1#')
networksetup -ordernetworkservices Wi-Fi "${service_list[@]}"
BTW,对于@userunknown和其他无法访问macOS试图解决/测试这个问题的人来说,这是一个示例输出:
$ networksetup -listnetworkserviceorder
An asterisk (*) denotes that a network service is disabled.
(1) iPhone USB
(Hardware Port: iPhone USB, Device: en5)
(2) Ethernet
(Hardware Port: Ethernet, Device: en0)
(3) Wi-Fi
(Hardware Port: Wi-Fi, Device: en1)
(*) FireWire
(Hardware Port: FireWire, Device: fw0)
(4) Bluetooth PAN
(Hardware Port: Bluetooth PAN, Device: en4)
(5) Thunderbolt Bridge
(Hardware Port: Thunderbolt Bridge, Device: bridge0)
答案 2 :(得分:1)
您似乎想重新排序网络端口,因此Wi-Fi
位于其他所有位置之前。
您尝试创建命令,就像在命令行上键入命令一样。虽然,这是一个将参数放在一个顺序中的问题。所以不要在网络名称周围加上引号,只要让参数代表它们自己,例如。
networksetup -listnetworkserviceorder | grep "Hardware Port" | grep -v "Wi-Fi" |
sed 's#([^:]*:\ \([^,]*\),.*#\1#'
现在您可以将它们与xargs
networksetup -listnetworkserviceorder | grep "Hardware Port" | grep -v "Wi-Fi" |
sed 's#([^:]*:\ \([^,]*\),.*#\1#' |
xargs networksetup -ordernetworkservices Wi-Fi
但是这并没有像预期的那样工作,因为硬件端口内部有空格(因此需要引用)。要解决此问题,您可以将硬件端口分隔为NUL字节而不是换行符。要用NUL字节替换换行符,请使用tr
networksetup -listnetworkserviceorder | grep "Hardware Port" | grep -v "Wi-Fi" |
sed 's#([^:]*:\ \([^,]*\),.*#\1#' | tr -s '\n' '\0' |
xargs -0 networksetup -ordernetworkservices Wi-Fi
现在xargs正确地将参数传递给networksetup。