2012-06-29 125 views

回答

23

沒有理由使用外部工具,如sed爲此; bash中能做到內部,using parameter expansion

如果要修剪後:的字符,例如:

$ str=foo_bar:baz 
$ echo "${str%%:*}" 
foo_bar 

中都可以貪婪和非貪婪的方式做到這一點:

$ str=foo_bar:baz:qux 
$ echo "${str%:*}" 
foo_bar:baz 
$ echo "${str%%:*}" 
foo_bar 

特別是如果你在一個緊密的循環中調用這個,啓動一個新的sed進程,寫入進程,讀取它的輸出並等待它退出(以獲得它的PID)可能會造成很大的開銷,處理內部的bash w沒有。


現在 - 通常,想要做到這一點的時候,你可能真的什麼是拆分變量進入領域,能更好地配合read完成。

舉例來說,假設你是從/etc/passwd讀線:

line=root:x:0:0:root:/root:/bin/bash 
IFS=: read -r name password_hashed uid gid fullname homedir shell _ <<<"$line" 
echo "$name" # will emit "root" 
echo "$shell" # will emit "/bin/bash" 

即使要處理從一個文件中多條線路,這也可以使用bash單獨做,沒有外部進程:

while read -r; do 
    echo "${REPLY%%:*}" 
done <file 

...將從file每一行發出一切直至第一:,而不需要任何分機ernal工具將被髮射。

8

什麼你要找的其實是很容易的:

sed 's/A.*//' 

A標誌着特定的字符。請注意,它是區分大小寫的,如果你想捕獲多個字符使用

sed 's/[aAbB].*//' 
2

如果文本包含文本,如

TEXT=beforexafter 

和特定的字符發生(例如)是x,然後

echo "${TEXT%x*}" 

你想要做什麼。

來砸,"$TEXT""${TEXT}"是整個beforexafter,但"${TEXT%xafter}"只是before,與xafter砍掉結束。要砍掉x及其後的任何東西,可以寫"${TEXT%x*}"。順便說一句,還有"${TEXT%%x*}"。只有當有多個x時,纔會有所不同。隨着%%,Bash砍掉所有x,而與%它只從最後x砍掉。你可以通過鬆散地觀察到更長的%%剔除更多文本。

你可以用桑達也這樣做,當然,如果你喜歡:

echo "$TEXT" | sed 's/x.*//' 
+2

請把周圍擴展報價 - '回聲$ TEXT'會做字符串分割,因此,如果'TEXT'包含'$ 'foo \ t \ tbar \ nbaz'',它會簡單地作爲'foo bar baz'出現,而'echo'$ TEXT「'不會出現這個缺陷。 (永久使用全大寫非環境變量的東西也是有點不幸;最好的做法是讓它們小寫以避免與環境變量和內建命名空間衝突)。 –

+0

@CharlesDuffy:你對引語是正確的:忽略它們是我的一個壞習慣,我應該從現在開始改革。關於全部大寫,你提出了一個有趣的觀點,更有趣的解釋。我懷疑你對帽子的建議是好的。 – thb

+1

不是問題,而是相關的。在''之後運行'echo'$ {TEXT#* x}「'' –

相關問題