使用文件结构
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。
答案 0 :(得分:3)
假设您定义乌克兰字母的字符类是正确的,以下内容应该有效:
sed '/[А-ЯЄЇІа-яєїі]/!d' file
[А-ЯЄЇІа-яєїі]
在线上任意位置匹配乌克兰字母。
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
修改:我编辑了这个答案,使其更简单,并为其添加循环。