2016-12-15 71 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来添加所有的乌克兰人物。 –