【问题标题】:Delete strings with non-Ukrainian characters bash删除带有非乌克兰字符bash的字符串
【发布时间】:2017-05-01 14:00:23
【问题描述】:

使用文件结构

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。

【问题讨论】:

  • 您的 sed 是否支持 + 修饰符?我的没有,所以我不得不写\{1,\}

标签: bash macos shell sed


【解决方案1】:

此代码将实现您想要的(如果我正确理解了您的问题):

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

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

【讨论】:

  • 即使在 OP 的字符类中 看起来 像 ASCII 字母 A I a i 的字母实际上也是具有 Unicode 代码点 @987654326 的 乌克兰(西里尔文)字母@
  • 我明白了。我不确定,乌克兰语不是我的强项:-p
  • 我会留给 OP 来添加所有的乌克兰字符。
  • @Jamil 说你写对了字母)你只是忘了包括范围 А-Я。我在 Stack 的某处读到上述范围仅包含俄语字母,因此我使用此解决方法添加了一些缺失的字母。可能还应该包括 Ґ 但这适合我的情况。
【解决方案2】:

假设您定义乌克兰字母的字符类是正确的,以下应该可以工作:

sed '/[А-ЯЄЇІа-яєїі]/!d' file
  • [А-ЯЄЇІа-яєїі] 匹配行中任意位置的乌克兰字母。
    • 请注意,即使是 看起来 像 ASCII 字母 A I a i 的字母实际上也是带有 Unicode 代码点 U+410 U+406 U+430 U+456乌克兰(西里尔文)字母。
  • ! 否定匹配,这意味着只有 not 包含至少 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,\}。 (\+ 仅受 GNU sed 支持,macOS 附带的 sed 的 BSD 版本不支持。

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

  • 您应该用双引号引用变量引用,例如 $i,以保护它们免受 shell 扩展:"$i"

  • BSD Sed 确实支持使用 -i 进行就地更新,但是 - 与 GNU Sed 不同 - 它需要指定一个空的选项参数(表示不应备份输入文件)单独的参数-i ''.

    • 您的 write-to-a-temp-file-first-then-replace-the-original 方法也有效,但通常最好使用以下成语:sed ... file > file.tmp && mv file.tmp file。将mv 命令与&& 分开可确保仅当sed 命令成功时才会替换原始文件。
      也就是说,这对解决当前案例中的逻辑错误没有帮助:尽管没有输出任何内容,sed 在这种情况下报告成功。

【讨论】:

  • 你的答案可能比我的好,因为它避免了mv 部分,所以我投票给你。
  • 谢谢,它成功了。但是,我不必使用sed -i '',即使我没有创建别名,但不知何故,常规sed 在这种情况下工作得很好。我不得不在其他情况下使用上述解决方法......
  • 另外,在每个文件的开头我都有字符串 l_ukrainian: 不知道为什么它没有被脚本删除,即使它很适合我。
  • @mklement0 你可能误读了 ` l_ukrainian ` 在我的情况下没有被删除。这让我很惊讶。
  • @AlCrow:啊,我明白了。这确实令人惊讶。将您的文件传送到cat -v 并查看是否有任何乌克兰字符。毕竟在第一行(例如U+456i)。 (但听起来你实际上想要保留那条线,对吧?)
猜你喜欢
  • 1970-01-01
  • 2013-11-12
  • 2018-02-22
  • 2011-08-21
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
  • 2010-12-04
相关资源
最近更新 更多