我有一个命令,它返回一个由引号包围的网络接口列表:-
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"我知道答案就在我面前,但我错过了。
发布于 2018-04-09 06:42:05
首先:在shell中,您应该把引号看作是数据周围的东西,而不是数据中的东西。你在你的数据中嵌入引号,期望它们就像在数据周围一样工作,但它并不是那样工作的。更具体地说,shell在替换变量值之前会解析引号(和转义以及其他一些东西),因此如果变量的值中有引号,那么当它被替换到命令行时,它就太晚了,无法达到预期的效果。
那么,当每个端口名可能包含空格时,您将如何维护它们作为一个单独的项呢?在bash中,您可以将它们存储在一个数组中,并使用"${arrayname[@]}"扩展数组--双引号和[@]的组合使得bash将每个数组元素作为一个单独的单词来处理,本质上就像每个项目都被单独引用一样。
那么如何将networksetup的输出输入到数组中呢?如果您有bash 4,您可以使用readarray,但是macOS只附带bash v3。你还是能做到的,只是再多做一点工作。您有一个read循环读取networksetup的每一行输出,处理后可以删除除服务名称之外的所有内容(并且没有添加引号)。但是,不能让循环成为管道的一部分,否则它将在子subshell中运行,退出时数据将丢失,因此必须用< <( )重定向循环的输入。就像这样:
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[@]}"顺便说一句,对于@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)发布于 2018-04-09 06:22:35
如果没有这样的网络设置程序,就很难说了。但是你看:
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">发布于 2018-04-09 06:57:27
您似乎希望重新排序网络端口,以便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正确地将参数传递给网络设置。
https://stackoverflow.com/questions/49725795
复制相似问题