删除非乌克兰字符bash的字符串

时间:2016-12-15 20:49:40

标签: bash macos shell sed

使用文件结构

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 个答案:

答案 0 :(得分: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在对该问题的评论中指出的那样,当+ 与{{1}一起运行时,sed不受支持}以启用扩展正则表达式;如果没有-E,则必须使用繁琐的-E。 (\{1,\}仅由 GNU \+支持,而不是由macOS附带的sed的BSD版本支持。

  • 但是,即使是命令的固定版本sed,也无法执行您想要的操作:它会删除包含至少一个非乌克兰字母字符的所有行,它消除了输入行的所有,因为它们都具有基于ASCII的字段名称并包含sed '/[^А-ЯЄЇІа-яєїі]\{1,\}/d'

  • 您应该引用:之类的变量引用来保护它们免受shell扩展的影响:$i

  • BSD Sed支持使用"$i"进行就地更新,但是 - 与GNU Sed不同 - 它要求指定一个空的option-argument(表示不应该对输入文件进行备份) 作为单独的参数-i

    • 您的写入临时文件首先然后替换原始方法也有效,但使用以下习语通常更好:-i ''。将sed ... file > file.tmp && mv file.tmp file命令与mv分开可确保仅在&&命令成功时才替换原始文件。
      也就是说,这并不像现有情况那样有助于解决逻辑错误:尽管没有输出,sed报告在这种情况下成功。

答案 1 :(得分: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

修改:我编辑了这个答案,使其更简单,并为其添加循环。