從 grep 的輸出中刪除匹配模式?
使用 bash,我正在執行:
declare -p | grep 'declare -- '
列印整行。我想列印那些相同的行,但我想排除匹配本身。即,我可以... | grep pattern | sed 's/pattern//'
作為單個命令執行嗎?這將與-o
選項相反。我的命令輸出這個:
... declare -- MAX_CONNECTIONS_PER_SERVER="6" declare -- OPTERR="1" declare -- OSTYPE="linux-gnu" ...
但我想輸出這個:
... MAX_CONNECTIONS_PER_SERVER="6" OPTERR="1" OSTYPE="linux-gnu" ...
通常情況下,我只是將它傳送到
sed
,但巧合的是,我今天想這樣做兩次。我查看了手冊頁,但沒有看到任何可以執行此操作的選項。在匹配模式之後只返回一行的一部分是一個非常相似的問題。也許它甚至是重複的。有人可能會爭辯說我的範圍更窄一些:可以保證我正在抓取的模式和我正在刪除的模式是相同的。我想刪除
x
. 問題要刪除.*x
。
如果可用,請使用
grep -P
:declare -p | grep -Po 'declare -- \K.*'
請注意,您的方法通常不會很好地工作,因為變數可能包含您將切斷的換行符
grep
並獲得語法錯誤。參見例如:
declare -- IFS=" "
那應該是:
declare -p | sed -n 's/^declare -- //p'
但是這種解析輸出的方法
declare -p
是有缺陷的。例如,如果環境中有 a
VAR=$'\ndeclare -- reboot #'
,並且您將該輸出提供給 shell 進行解釋,該怎麼辦?另請注意,對於已聲明但未分配任何值的變數,將
bash
列印:declare -- VARNAME
,因此在 之後declare reboot
,上述程式碼也會輸出reboot
。您可以將其更改為:
declare -p | LC_ALL=C sed -n 's/^declare -- \(.*=\)/\1/p'
限制為分配的變數,但這仍然不能解決包含換行符的變數的問題(即使僅針對
$TERMCAP
變數也很常見)。相反,您可以使用這種 hack:
( export LC_ALL=C eval ' declare() if [[ $1 = -- ]]; then printf "%s=%q\n" "${2%%=*}" "${2#*=}" fi'" $(declare -p | sed 's/[][()]/\\&/g')" )
在我們重新定義為一個函式之後,我們在哪裡評估
declare -p
我們轉義的地方的輸出(
,並在數組和關聯數組表示中使用,如果第一個參數是 ,則列印它的第二個參數。使用風險自負,過去已知 bash 的輸出對於評估是不安全的,添加轉義也可能會增加複雜性,特別是對於它們接受的行長度有限制的實現。)``[``]``declare``--``declare -p``sed``sed
在 中
zsh
,你可以這樣做:typeset ${(k)parameters[(R)scalar]}
列印標量變數的定義並且沒有任何屬性(甚至不是special也不是linked),這似乎是您的意圖。
typesetsilent
但是請注意,如果在函式中呼叫(在這種情況下,它將所有這些變數聲明為本地變數)或啟用該選項,則它不起作用。另一種可以解決這個問題並讓您更好地控制如何引用值的方法是:
() for 1 do print -r -- $1=${(Pq+)1}; done ${(k)parameters[(R)scalar]}
q+
給出與 . 使用的引用風格相似的引用風格typeset
。如果您打算在 shell 中使用該輸出(可能不是 zsh,或者不是來自同一版本,或者不在相同的語言環境或 OS/libc 中),請使用