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

3
使用文件结构
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终端。


2
你的sed支持+修饰符吗?我的不支持,所以我必须写成\{1,\} - Stefan Hegny
2个回答

4
假设您定义乌克兰字母的字符类是正确的,那么以下内容应该有效:
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

关于你尝试过的内容:
- 如问题中的评论所指出,当不使用-E以启用扩展正则表达式时,+sed中不受支持; 无-E时,必须使用复杂的\{1,\}。(\+仅由GNU版sed支持,而非macOS附带的BSD版本sed)。 - 然而,即使是您的命令的修正版本 sed '/[^А-ЯЄЇІа-яєїі]\{1,\}/d' 也不能做到您想要的:它删除所有包含至少一个非乌克兰字母字符的行,这会消除您的所有输入行,因为它们都有基于ASCII的字段名并包含:。 - 您应该将变量引用(例如$i)放在双引号中以保护它们免受shell扩展的影响:"$i"。 - BSD Sed确实支持使用-i进行地点更新,但与GNU Sed不同,它需要指定空选项参数(表示不需要备份输入文件)作为单独的参数:-i'' 。 - 您先写入临时文件,然后再替换原始文件的方法也可以,但通常最好使用以下惯用语: sed ... file > file.tmp && mv file.tmp file 。使用&&分隔mv命令可确保仅在sed命令成功后才替换原始文件。
也就是说,在这种情况下,即使不输出任何内容,sed仍会报告成功。

1
你的答案可能比我的更好,因为它避免了 mv 部分,所以我投了你一票。 - Jamil Said
谢谢,它起作用了。但是,我不必使用 sed -i '',即使我没有创建别名,不知何故,在这种情况下常规的 sed 也可以正常工作。虽然在其他情况下我不得不使用上述解决方法... - Al Crow
此外,在每个文件的开头,我都有字符串_l_ukrainian:_,不确定为什么脚本没有将其删除,尽管它很适合我。 - Al Crow
@mklement0,您可能误读了我的情况,l_ukrainian并没有被删除。这让我感到惊讶。 - Al Crow
@AlCrow:啊,我明白了。确实令人惊讶。将您的文件导入到 cat -v 并查看第一行是否有任何乌克兰字符(例如 U+456 i)。 (但是听起来您实际上是想保留那一行,对吗?) - mklement0
显示剩余3条评论

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

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


即使在 OP 的字符类中看起来像 ASCII 字母 A I a i 的字母实际上是乌克兰(西里尔文)字母,其 Unicode 代码点为 U+410 U+406 U+430 U+456 - mklement0
我明白了。我不太擅长乌克兰语 :-p - Jamil Said
我将让OP添加所有乌克兰字符。 - Jamil Said
@JamilSaid,你的字母是正确的,但你忘记了包括区间А-Я。我在_Stack_上读到过这个范围只包括俄语字母,所以我使用了这种解决方法添加了一些缺失的字母。也许还应该包括Ґ,但这对我的情况已经足够了。 - Al Crow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接