2016-12-15 70 views
3

刪除字符串中使用的文件結構與非烏克蘭字符的bash

foo_11: "Марія" 
foo_112: "Superman" 
FOOTLONG: "Subway" 
foo_13: "Юлія" 

我想刪除沒有從烏克蘭字母表至少一個字符的所有字符串。

腳本:

for i in *.txt; 
do 
sed '/[^А-ЯЄЇІа-яєїі]+/d' $i >$i.out 
mv $i.out $i 
done 

沒有做任何事情。哪裏不對?

使用mac bash。

+2

你的sed是否支持'+'修飾符?礦井沒有,所以我不得不寫'\ {1,\}'而不是 –

回答

3

假設你的性格類中定義的烏克蘭字母是正確的,下面應該工作:

sed '/[А-ЯЄЇІа-яєїі]/!d' file 
  • [А-ЯЄЇІа-яєїі]烏克蘭字母就行的任何地方匹配。
    • 注意,即使是看起來 ASCII字母A I a i字母實際上烏克蘭(西里爾)字母與Unicode代碼點U+410 U+406 U+430 U+456
  • !否定匹配,這意味着只有線含有至少1烏克蘭語的字母匹配。
  • d刪除這些行。

爲了把它放在一起:

for f in *.txt; do 
    sed -i '' '/[А-ЯЄЇІа-яєїі]/!d' "$f" # -i '' is BSD Sed syntax; GNU sed takes just -i 
done 

至於你已經嘗試過什麼:

  • 由於@StefanHegny在關於這個問題的評論指出,+sed是爲了使運行與-E不支持擴展正則表達式;沒有-E,必須使用繁瑣的\{1,\}。 (\+僅由GNUsed支持,不是由sed的BSD版本的MacOS自帶)。

  • 不過,即使你的命令,sed '/[^А-ЯЄЇІа-яєїі]\{1,\}/d'的固定版本,不會做你想要的東西:它刪除包含至少一個非烏克蘭的字母字符,免去所有的所有的行輸入行,因爲它們都具有基於ASCII的字段名稱幷包含:

  • 你應該用雙引號變量引用如$i保護他們免受shell擴展:"$i"

  • BSD桑達不支持就地更新與-i,但是 - 不像GNU桑達 - 它需要的是一個空選項形式參數(指示沒有輸入文件的備份應)來指定作爲單獨的參數-i ''

    • 你寫對一個-TEMP文件先,然後替換最原始的方法也工作,但它通常最好使用下面的語句:sed ... file > file.tmp && mv file.tmp file。與&&分離mv命令確保如果sed命令成功執行原來的文件只更換。
      這就是說,不與邏輯錯誤,在手的情況下幫助:儘管輸出什麼,在這種情況下sed報告成功。
+1

你的回答可能比我的好,因爲它避免了「mv」部分,所以我投票給你。 –

+0

謝謝,它的工作。然而,我並不需要使用'sed -i''',即使我沒有創建別名,不知何故,在這種情況下,普通的'sed'工作得很好。我不得不在其他情況下使用上述解決方法,但...... –

+0

此外,在每個文件的開頭我有字符串_l_ukrainian:_不知道爲什麼它沒有被腳本刪除,儘管它很適合我。 –

2

此代碼將實現你想要的(如果我理解正確你的問題):

grep -i "Я\|Є\|Ї\|І" /folder/file >> /tmp/result 

結果存儲在/tmp/result

注:我不知道烏克蘭,所以我我確定我沒有包括所有的烏克蘭字符,請添加/刪除你想匹配的烏克蘭字符到上面的建設。

注2:這個代碼是區分大小寫的感謝grep -i所以你只需要添加一次字符(小寫或大寫)。

把它放在你的循環可能是:

for i in *.txt; 
do 
grep -i "Я\|Є\|Ї\|І" "$i" > "$i".out 
mv "$i".out "$i" 
done 

編輯:我編輯這個答案,使其更簡單,並移交給循環添加到它。

+0

即使是像_look_ ASCII字母'在OP的字符類AI ai'字母實際上是_Ukrainian_(西里爾)字母與Unicode代碼點' U + 410 U + 406 U + 430 U + 456' – mklement0

+0

我明白了。我不確定,烏克蘭人真的不是我的強項:-p –

+0

我會留給OP來添加所有的烏克蘭人物。 –