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

删除带有非乌克兰字符的字符串bash,bash,macos,shell,sed,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。此代码将实现您想要的功能(如果我正确理解了您的问题): 结果存储在/tmp/r

使用文件结构

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。

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

结果存储在
/tmp/result

注意:我不知道乌克兰语,所以我确定我没有包括所有乌克兰语字符,请添加/删除您希望与上述结构匹配的乌克兰语字符。

注2:由于
grep-i
的原因,此代码不区分大小写,因此只需添加一次字符(小写或大写)

要将其放在循环中,可以是:

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

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

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

sed '/[А-ЯЄЇІа-яєїі]/!d' file
  • [А-ЯЯа-єїі]
    匹配行中任何位置的乌克兰字母。
    • 请注意,即使看起来像ASCII字母
      aii
      的字母实际上也是带有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,\}
    。(
    \+
    仅受GNU
    sed
    支持,而不受macOS附带的BSD版本的
    sed
    支持)

  • 但是,即使是命令的固定版本,
    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文件
      。将
      mv
      命令与
      和&
      分开可确保仅当
      sed
      命令成功时才替换原始文件。
      这就是说,这对处理逻辑错误并没有帮助,就像在本例中一样:尽管没有输出任何内容,
      sed
      报告了本例中的成功

您的sed是否支持
+
修饰符?我的没有,所以我必须写
\{1,\}
而不是,即使是OP字符类中看起来像ASCII字母
aiai
的字母,实际上也是带有Unicode码点的乌克兰(西里尔文)字母
U+410 U+406 U+430 U+456
。我不确定,乌克兰语不是我的强项:-pI将留给OP添加所有乌克兰语字符。@Jamil说你写对了字母)你只是忘了包含范围A-Я。我在堆栈上的某个地方读到,上面的范围仅包括俄语字母,因此我使用此解决方法添加了一些缺少的字母。一个人可能也应该包括Ґ,但这适合我的情况。你的答案可能比我的好,因为它避免了
mv
部分,所以我选了你。谢谢,它成功了。然而,我不必使用
sed-I'
,即使我没有创建别名,在这种情况下,常规的
sed
也可以正常工作。不过,我不得不在其他情况下使用上述解决方法……此外,在每个文件的开头,我都有字符串l_ukrainian:不确定为什么脚本没有删除它,尽管它很适合我。@mklement0您可能误读了“l_ukrainian”在我的情况下没有删除。阿尔克罗:啊,我明白了。这确实令人惊讶。将您的文件传送到
cat-v
,查看是否有乌克兰字符。毕竟在那第一行(比如a
U+456
i
)。(但听起来你真的想保持这条线,对吗?)
for f in *.txt; do 
  sed -i '' '/[А-ЯЄЇІа-яєїі]/!d' "$f"    # -i '' is BSD Sed syntax; GNU sed takes just -i
done