簡體   English   中英

使用 sed 替換長度相等的文本

[英]substitute text with equal length using sed

有沒有辦法使用 sed 替換具有相同長度的其他內容(例如點、零等)的模式? 像這樣:

maci:/ san$ echo "She sells sea shells by the sea shore" | sed 's/\(sh[a-z]*\)/../gI'
.. sells sea .. by the sea ..

“I”需要更新版本的 sed 才能忽略大小寫
這很簡單:以“sh”開頭的單詞被雙點 (..) 取代,但我如何使它成為這樣的: ... sells sea ...... by the sea .....

任何的想法? 干杯!

我懷疑你不能在標准sed做到這一點,但你可以用 Perl 或其他更強大的正則表達式處理來做到這一點。

$ echo "She sells sea shells by the sea shore" |
> perl -pe 's/(sh[a-z]*)/"." x length($1)/gei'
... sells sea ...... by the sea .....
$

e修飾符表示替換模式是可執行的 Perl 腳本; 在這種情況下,它會重復字符. 與匹配模式中的字符一樣多。 g修飾符在行中重復; i修飾符用於不區分大小寫的匹配。 Perl 的-p選項在-e選項指定的腳本中處理后打印每一行 - 替代命令。

這個 awk-oneliner 能幫您完成這項工作嗎?

awk '{for(i=1;i<=NF;i++)if($i~/^[Ss]h/)gsub(/./,".",$i)}1' file

用你的數據測試:

kent$  echo "She sells sea shells by the sea shore"|awk '{for(i=1;i<=NF;i++)if($i~/^[Ss]h/)gsub(/./,".",$i)}1'
... sells sea ...... by the sea .....

一個老問題,但我發現了一個不錯的、相對較短的單行 sed 解決方案:

sed ':a;s/\([Ss]h\.*\)[^\. ]/\1./;ta;s/[Ss]h/../g'

通過在循環中一次替換一個字符來工作。

:a; 開始一個循環

s/\\([Ss]h\\.*\\)[^\\. ] s/\\([Ss]h\\.*\\)[^\\. ]搜索一個sh后跟任意數量的. s(到目前為止我們完成的工作)后跟一個非點或空格字符(我們將要替換的內容)

/\\1./; 用我們迄今為止完成的工作加上另一個來代替它. .

ta; 如果我們做了任何替換,循環,否則......

s/[Ss]h/../gsh替換為兩個. s 並收工。

$ echo "She sells sea shells by the sea shore" |
awk '{
   head = ""
   tail = $0
   while ( match(tolower(tail),/sh[a-z]*/) ) {
      dots = sprintf("%*s",RLENGTH,"")
      gsub(/ /,".",dots)
      head = head substr(tail,1,RSTART-1) dots
      tail = substr(tail,RSTART+RLENGTH)
   }
   print head tail
}'
... sells sea ...... by the sea .....

正如其他人所指出的,sed 不太適合這項任務。 這當然是可能的,這里有一個例子,它適用於用空格分隔的單詞的單行:

echo "She sells sea shells by the sea shore" |

sed 's/ /\n/g' | sed '/^[Ss]h/ s/[^[:punct:]]/./g' | sed ':a;N;$!ba;s/\n/ /g'

輸出:

... sells sea ...... by the sea .....

第一個'sed'用換行符替換空格,第二個做點,第三個刪除換行符,如本答案所示

如果您有不可預測的單詞分隔符和/或段落,這種方法很快就會變得難以管理。

編輯 - 多行替代品

這是處理多行輸入的一種方法,靈感來自Kent 的評論 (GNU sed):

echo "
She sells sea shells by the sea shore She sells sea shells by the sea shore,
She sells sea shells by the sea shore She sells sea shells by the sea shore
 She sells sea shells by the sea shore She sells sea shells by the sea shore
" |

# Add a \0 to the end of the line and surround punctuations and whitespace by \n 
sed 's/$/\x00/; s/[[:punct:][:space:]]/\n&\n/g' |

# Replace the matched word by dots
sed '/^[Ss]h.*/ s/[^\x00]/./g' | 

# Join lines that were separated by the first sed
sed ':a;/\x00/!{N;ba}; s/\n//g'

輸出:

... sells sea ...... by the sea ..... ... sells sea ...... by the sea .....,
... sells sea ...... by the sea ..... ... sells sea ...... by the sea .....
 ... sells sea ...... by the sea ..... ... sells sea ...... by the sea .....

這可能對你有用(GNU sed):

sed -r ':a;/\b[Ss]h\S+/!b;s//\n&\n/;h;s/.*\n(.*)\n.*/\1/;s/././g;G;s/(.*)\n(.*)\n.*\n/\2\1/;ta' file

在本質上; 它復制以shSh開頭的單詞,將每個字符替換為. 然后將新字符串重新插入原始字符串。 當搜索字符串的所有出現都用完時,它會打印出該行。

替代:

sed -E 's/\S+/\n&/g;s#.*#echo "&"|sed "/^sh/Is/\\S/./g"#e;s/\n//g' file

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM