2017-02-27 182 views
0

我想從文件中刪除特定的單詞。從字符串中刪除單詞

比方說文件名agent_file.txt包含以下字符串

-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,process,winprocess 

我想刪除字符或僅在該文件中的字process,所以我的Unix

下使用下面的命令
perl -pi -e 's/process//g' agent_file.txt 

輸出將是

-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,,win 

這個詞是delet編輯,但它也刪除winprocess的一部分。

如何刪除process以及前面的逗號,

輸出應該

-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess 

回答

0

如果它是逗號分隔的,請用它們來表達它的優點。

perl -pi -e "s/, \s* process\s* , /, /g filename 

如果有不會是空格或之前逗號,然後刪除\ S *後

0

你可以做三個步驟

sed 's/,process,/,/g;s/^process,//;s/,process$//' 

的職位測試,:在兩者之間,開始或結尾。

+0

'\ b'似乎是GNU專用的。此解決方案在OS X或* BSD中不起作用。 – ghoti

+0

謝謝@karakfa這有助於很多,但是這隻適用於GNU sed ...但不能在AIX下的sed中工作... =( – MrAZ

+0

這不會刪除多餘的前導或尾隨逗號,如果'process'出現在列表的開頭或結尾 – Borodin

1

使用自動分割(-a)用逗號(-F,),避免逗號問題完全

perl -F, -lane 'print join ",", grep { not /^process$/ } @F' input > output 

輸入由,分解爲@F。該grep過濾掉字,其餘由,

加入回爲了改變地方輸入文件添加-i和下降> output

Command switches in perlrun


的問題是,第一個和最後一個單詞有一個逗號,如果它們被刪除需要去,而另一個逗號需要留下兩個逗號。與正則表達式的一種方式是做兩遍,刪除單詞,然後額外的逗號(仍然要小心第一個和最後一個)。在更換部件

或運行的代碼來選擇適當的情況下

echo "go,stay,ago,go,got,end,go" | 

    perl -pe's/(,)?\bgo\b(,)?/$1 && $2 && ","/ge' 

打印:stay,ago,got,end/e將替換端評估爲Perl代碼。

如果兩個逗號都存在($1 && $2),則用(&&)替換爲逗號(",")。

這工作,因爲在Perl && returns the value

||//&&操作符返回最後計算的值(與C不同的||&&,它返回0或1)。

1

這是awk解決方案。

awk 'BEGIN{OFS=FS=","} {for(i=1;i<=NF;i++) if($i=="process") $i=""} 1' file 

此功能可設置字段分隔符爲逗號輸入和輸出,然後一步一步地你的領域,檢查對您感興趣的字符串等價和排空領域是否匹配。最後的1對於「打印當前行」來說簡直就是awk。


類似的,可以通過記錄,而不是由場分好輸入數據:

awk 'BEGIN{ORS=RS=","} /^process$/{next} 1' file 

awk 'BEGIN{ORS=RS=","} $0=="process"{next} 1' file 

這走過你的輸入使用逗號作爲記錄分隔符( RS),這樣可以使用awk的記錄感知評估單個單詞。你可以通過正則表達式來進行評估 - 正則表達式稍微慢一些,但似乎爲你節省了兩個字符的輸入。 :-)

使用RS/ORS的策略消除了您注意到字段被清空但未刪除的問題。當逗號是記錄分隔符時,則跳過的記錄會導致不顯示記錄分隔符,這更接近您在問題中包含的「理想」輸出。


最後一個選項可能是在你的shell(ksh)中執行此操作。這將具有最大可移植性的優點(您不必擔心perl版本,無論awk/sed是GNU還是BSD或其他)。缺點是使用下面的方法時,您的文件大小將受到系統內存限制(可能還有可配置的限制)。

$ IFS=, read -A arr < file 
$ for i in "${!arr[@]}"; do [[ "${arr[$i]}" == "process" ]] && unset arr[$i]; done 
$ output=$(printf "%s," "${arr[@]}") 
$ echo "${output%,}" 
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess 

注意,$output變量是爲了通過剝離產生printf後面的逗號時才需要。另一種選擇可能是設置$IFS更加全球化:

$ IFS=, 
$ echo "${arr[*]}" 
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess 

我要指出,儘管表面上看起來,在printf選項並沒有真正產卵外部命令,因爲KSH實現printf作爲內置。

0

這個可能嗎?

它搜索所有出現的process,使用單詞邊界來確保它不是作爲另一個單詞的一部分找到的,並且還匹配前後的可選逗號,。本場比賽是由一個逗號取代,如果發現兩個逗號(process在列表中找到),如果有刪除,只有一個(process只出現在開頭或列表的末尾)

perl -pi -e 's/ ,? \b process \b ,?)/$1 =~ tr/,// > 1 ? ',' : '' /xge' agent_file.txt 
0
awk '{sub(/process,/,"")}1' file