我正在嘗試讓腳本偵聽 stdin(所以我運行它并且它不會立即退出)并且僅在 stdin 不為空時執行,然后將 stdin 行通過管道傳輸到另一個命令。現在我正在使用這里的答案中的命令:
xargs -I {} sh -c 'echo {} | foo'
我想保留標準輸入中的雙引號,因為人們建議使用,-d '\n'但這會導致 foo 在空行上運行。
我研究了可能的 GNU Parallel 解決方案,但找不到任何東西。
這是我的標準輸出:
>xargs -I {} sh -c 'echo {} | foo'
bar
I have executed for 'bar'
"bar"
I have executed for 'bar' //notice the double quotes missing
^C
>xargs -I {} sh -c "echo '{}' | foo"
bar
I have executed for 'bar'
"bar"
I have executed for 'bar' //Same thing, double quotes missing
^C
>xargs -d '\n' -I {} sh -c "echo {} | foo"
i have executed for '' //doesn't ignore empty lines anymore
i have executed for ''
bar
i have executed for 'bar'
"bar"
i have executed for 'bar'
期望的輸出:
bar
I have executed for 'bar'
"bar"
I have executed for '"bar"'
跑步
echo '"bar"' | foo
得到我
I have executed for '"bar"'
uj5u.com熱心網友回復:
如果,正如你的標簽所暗示的,你正在運行 linux,您有 GNU xargs,它支持該-0選項。然后,您可以傳入完全任意的文本,甚至包括換行符:
printf '%s\0' "foo" "'bar"' '"baz"' 'quux
with a newline' | xargs -0 foo
洗掉空行可以通過簡單grep的前面來完成。還有xargs -r一個說如果xargs收到空輸入則不運行命令(這也是一個 GNU 擴展)。
不過,您的嘗試有點問題;您應該將引數作為命令列引數傳遞,而不是將xargs它們sh -c '... {} ...'逐字插入到字串中。
稍微取決于您的要求,這甚至可以在其他平臺上便攜地作業:
xargs sh -c 'if [ $# -gt 0 ]; then echo "$@" | foo; fi' _
該_只是一個占位符; 的引數sh -c '...'用于填充$0, $1,$2等,因此我們放入一些東西,任何東西,以占據$0.
uj5u.com熱心網友回復:
GNU Parallel 在內部使用它:
perl -e 'if(sysread(STDIN,$buf,1)){open($fh,"|-",@ARGV)||die;syswrite($fh,$buf);if($read=sysread(STDIN,$buf,131071)){syswrite($fh,$buf);}while($read=sysread(STDIN,$buf,131072)){syswrite($fh,$buf);}close$fh;exit($?&127?128 ($?&127):1 $?>>8)}' /usr/bin/bash -c 'wc -l'
如果您只想要一行,請嘗試:
seq 3 | parallel --pipe -N1 wc -c
echo "'foo'" | parallel --pipe -N1 --rrs "echo -n i have executed for \"'\";cat;echo \"'\""
echo '"foo"' | parallel --pipe -N1 --rrs "echo -n i have executed for \"'\";cat;echo \"'\""
uj5u.com熱心網友回復:
我想保留標準輸入中的雙引號,因為人們建議使用 -d '\n' 但這會導致 foo 在空行上運行。
xargs默認情況下執行報價處理,除非您通過-d/--delimiter或-0/指定分隔符--null。您必須使用其中之一來避免xargs洗掉您試圖保留的引號。
更重要的是,假設您設法通過xargs不變地傳遞參考的輸入,xargs 啟動以運行命令的 shell 將執行自己的參考洗掉,以及引數擴展、變數分配、重定向處理等。您可以通過此變體直接觀察其對命令的影響:
$ xargs -d '\n' -I{} sh -c 'echo {} >>tmp.txt'
bar
'bar'
$ cat tmp.txt
bar
bar
$
請注意,盡管為 指定了分隔符,但引號仍被洗掉xargs。
決議您的確切要求有點困難,但聽起來您只想從某些命令的標準輸入中過濾空行。 sed可以很容易地做到這一點:
foo() {
while IFS= read -r line; do
echo "I have executed for '$line'"
done
}
$ sed '/\S/!d' | foo
bar
"bar"
A whole line with "quotes" and 'quotes' and metacharacters > < !
I have executed for 'bar'
I have executed for '"bar"'
I have executed for 'A whole line with "quotes" and 'quotes' and metacharacters > < !'
$
sed命令說明:正則運算式/\S/匹配行上任何位置的任何非空白字符。所述!否定匹配,并且d洗掉線匹配(否定)模式-這是一種不含有至少一個非空字符的任何行。
正如您在示例運行腳本中看到的那樣,示例命令之間的緩沖與使用sed. 目前尚不清楚這對您是否重要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/391889.html
上一篇:問題理解bash腳本中的引數擴展
