Linux sed:删除包含字符类的整个单词
我想从文本文件中删除任何包含非alpha字符的单词。e、 gLinux sed:删除包含字符类的整个单词,linux,bash,command-line,awk,sed,Linux,Bash,Command Line,Awk,Sed,我想从文本文件中删除任何包含非alpha字符的单词。e、 g "ok 0bad ba1d bad3 4bad4 5bad5bad5" 应该成为 "ok" 我试过使用 echo "ok 0bad ba1d bad3 4bad4 5bad5bad5" | sed 's/\b[a-zA-Z]*[^a-zA-Z]\+[a-zA-Z]*\b/ /g' 使用awk: s="ok 0bad ba1d bad3 4bad4 5bad5bad5" awk '{ofs=""; for (i=1; i<=
"ok 0bad ba1d bad3 4bad4 5bad5bad5"
应该成为
"ok"
我试过使用
echo "ok 0bad ba1d bad3 4bad4 5bad5bad5" | sed 's/\b[a-zA-Z]*[^a-zA-Z]\+[a-zA-Z]*\b/ /g'
使用
awk
:
s="ok 0bad ba1d bad3 4bad4 5bad5bad5"
awk '{ofs=""; for (i=1; i<=NF; i++) if ($i ~ /^[[:alpha:]]+$/)
{printf "%s%s", ofs, $i; ofs=OFS} print ""}' <<< "$s"
ok
首先
grep-o
将字符串拆分为单个单词。第二个grep只搜索带有字母的单词。最后,tr
将\n
转换为空格。使用awk
:
s="ok 0bad ba1d bad3 4bad4 5bad5bad5"
awk '{ofs=""; for (i=1; i<=NF; i++) if ($i ~ /^[[:alpha:]]+$/)
{printf "%s%s", ofs, $i; ofs=OFS} print ""}' <<< "$s"
ok
st="ok 0bad ba1d bad3 4bad4 5bad5bad5"
for word in $st;
do
if [[ $word =~ ^[a-zA-Z]+$ ]];
then
echo $word;
fi;
done
首先
grep-o
将字符串拆分为单个单词。第二个grep只搜索带有字母的单词。最后,tr
将\n
转换为空格。如果您不担心在每个单词之间丢失不同数量的空格,您可以在Perl中使用如下内容:
st="ok 0bad ba1d bad3 4bad4 5bad5bad5"
for word in $st;
do
if [[ $word =~ ^[a-zA-Z]+$ ]];
then
echo $word;
fi;
done
perl -ane 'print join(" ", grep { !/[^[:alpha:]]/ } @F), "\n"
-a
开关启用自动拆分模式,将文本拆分为任意数量的空格,并将字段存储在数组@F
中grep
过滤掉该数组中包含任何非字母字符的元素。结果数组在单个空格上联接。如果您不担心在每个单词之间丢失不同数量的空格,您可以在Perl中使用如下内容:
perl -ane 'print join(" ", grep { !/[^[:alpha:]]/ } @F), "\n"
-a
开关启用自动拆分模式,将文本拆分为任意数量的空格,并将字段存储在数组@F
中grep
过滤掉该数组中包含任何非字母字符的元素。生成的数组在单个空间上联接。以下sed命令执行此操作:
sed 's/[[:space:]]*[[:alpha:]]*[^[:space:][:alpha:]][^[:space:]]*//g'
它删除至少包含一个非字母字符的所有单词。最好使用POSIX字符类,如<代码> [Alph::] /Cord>,因为例如,他们不会认为法语名字“弗兰Cou-OIS”是错误的(即包含非字母字符)。
解释
我们删除所有模式,从任意数量的空格开始,后跟任意(可能为零)数量的字母字符,后跟至少一个非空格和非字母字符,然后全局移动到单词的末尾(即,直到下一个空格)。请注意,您可能希望将[:space://code>替换为[:blank://code>,有关这两个POSIX类之间差异的详细说明,请参阅
测验
以下sed命令执行此任务:
sed 's/[[:space:]]*[[:alpha:]]*[^[:space:][:alpha:]][^[:space:]]*//g'
它删除至少包含一个非字母字符的所有单词。最好使用POSIX字符类,如<代码> [Alph::] /Cord>,因为例如,他们不会认为法语名字“弗兰Cou-OIS”是错误的(即包含非字母字符)。
解释
我们删除所有模式,从任意数量的空格开始,后跟任意(可能为零)数量的字母字符,后跟至少一个非空格和非字母字符,然后全局移动到单词的末尾(即,直到下一个空格)。请注意,您可能希望将[:space://code>替换为[:blank://code>,有关这两个POSIX类之间差异的详细说明,请参阅
测验
这可能适用于您(GNU-sed):
这将在alternation中使用back引用来保存所需的字符串。这可能适用于您(GNU-sed):
这将在alternation中使用back引用来保存所需的字符串。要删除的是非字母还是数字?你的尝试有什么问题?都是非字母的,不仅仅是数字。它产生了一个错误的答案。您要删除的是非字母,还是数字?你的尝试有什么问题?都是非字母的,不仅仅是数字。它产生了一个错误的答案。@Dimid:我在我的答案中添加了解释。我重复下面写的评论:请使用[[:alpha:]
而不是buggy[a-zA-Z]
,因为如果您在s
中用“Öcalan”替换您的“ok”,例如,您的脚本将输出一个空字符串:(@Jotne-在某些awk(例如OSX awk)中,print
将根据三元表达式中的条件在print()时导致语法错误)
总是会成功的。我不确定是否有其他情况下,未括号化的三元表达式会失败,也不知道仅仅在表达式的条件部分加括号是否足以解决这一问题。我个人觉得用括号化整个表达式更容易阅读,而且我知道它在所有情况下都有效tuations所以我就这么做了。我实际上在OSX上工作,并使用awk的默认OSX版本在awk上面进行了测试。但是,是的,为了更好的兼容性,似乎最好使用(iYes),正如我提到的,您的解决方案是添加一个尾随空白字符,而不提供换行符。您需要awk'{ofs=“”;用于(i=1;i@Dimid:我在回答中添加了解释。我重复下面的评论:请使用[[:alpha:]
而不是buggy[a-zA-Z]
,因为如果您在s
中用“Öcalan”替换您的“ok”,例如,您的脚本将输出一个空字符串。:(@Jotne-在某些awk中(例如OSX awk)print
在print()时,根据三元表达式中的条件,将导致语法错误
总是会成功的。我不确定是否有其他情况下,未括号化的三元表达式会失败,也不知道仅仅在表达式的条件部分加括号是否足以解决这一问题。我个人觉得用括号化整个表达式更容易阅读,而且我知道它在所有情况下都有效tuations所以我就这么做了。我实际上在OSX上工作,并使用awk的默认OSX版本在awk上面进行了测试。但是,是的,为了更好的兼容性,似乎最好使用(iYes),正如我提到的,您的解决方案是添加一个尾随空白字符,而不提供换行符。您需要awk'{ofs=“”;用于(i=1;i+1,我自己也在尝试沿着这些思路解决一些问题*