Bash 使用grep或sed替换与模式不匹配的单词
我是正则表达式范例的新手,我遇到了一个我正试图解决的问题,但没有成功 设想一个文件test.txt包含:Bash 使用grep或sed替换与模式不匹配的单词,bash,shell,awk,sed,grep,Bash,Shell,Awk,Sed,Grep,我是正则表达式范例的新手,我遇到了一个我正试图解决的问题,但没有成功 设想一个文件test.txt包含: hello everyone, whatsi up i hope my program worksa if it doesnt... ho well! 我只想将以辅音开头、以元音结尾的单词输出到另一个文件output.txt,这样会导致: hello whatsi hope worksa ho 我正在使用grep-o'\b[^aeiouAEIOU]\w*[aeiouAEIOU]\b'te
hello everyone, whatsi up
i hope my program worksa
if it doesnt... ho well!
我只想将以辅音开头、以元音结尾的单词输出到另一个文件output.txt,这样会导致:
hello whatsi
hope worksa
ho
我正在使用grep-o'\b[^aeiouAEIOU]\w*[aeiouAEIOU]\b'test.txt>output.txt
,但是,-o
标志将每个匹配的字符串输出到新行。我应该怎么做才能得到我想要的格式?另一个有效的选择是使用sed将所有与该模式不匹配的内容替换为一个空格,但我也没有这样做。我应该使用sed还是awk
谢谢使用
-n
选项输出行号,然后可以重新组合匹配项
例如,在Perl中:
grep -no '\b[^ aeiouAEIOU]\w*[aeiouAEIOU]\b' test.txt \
| perl -aF: -nwE 'chomp $F[1];
push @{ $b[ $F[0] ] }, $F[1]
}{ say "@$_" for grep defined, @b'
Perl本身在这里可以很好地工作:对于每一行,找到符合条件的每个单词
perl -lane 'print join " ", grep {/\b[bcdfghjklmnpqrstvwxyz][[:alpha:]]*[aeiou]\b/i} @F' file
- 使用
将行拆分为单词,存储在数组-a
@F
将仅过滤与正则表达式匹配的单词grep
- 然后用空格连接结果列表并打印出来。
- 如果行上没有匹配的单词,则将打印一个空行
perl -lape'$_="@{[grep{/\b(?=[a-z])[^aeiou][a-z]*[aeiou]\b/i}@F]}"' file
请注意,一个数字与
[^aeiou]
匹配,这就是为什么我添加了lookahead(?=[a-z])
,以限制单词的第一个字符为字母,而不是元音。以下awk解决方案也可以帮助您做到这一点
awk '{for(i=1;i<=NF;i++){if(tolower($i) ~ /^[^aeiou].*[aeiou]$/){val=val?val OFS $i:$i}};print val;val=""}' Input_file
在这里添加一个非一行表单并进行解释
awk '{
for(i=1;i<=NF;i++){ ##Starting a for loop here which starts from variable i value from 1 to till the value of NF(number of fields) value.
if(tolower($i) ~ /^[^aeiou].*[aeiou]$/){ ##checking here condition if a field value in lower is satisfying the regex where I am checking if a value NOT starts from vowel and it is ending with vowels.
val=val?val OFS $i:$i ##Creating a variable named val which will have value of current field value and it will concatenate its own value.
}
};
print val; ##Outside of loop, I am printing the value of variable val here, which will have all those words which are satisfying your conditions.
val="" ##Nullifying the value of variable val here.
}
' Input_file ##Mentioning the Input_file name here.
awk'{
对于(i=1;i在grep
中的-p
的帮助下
它的工作原理
-p
用于使用PCRE
模式遵循以下步骤:
它不匹配单词开头的任何[aieuo]
然后匹配一些字符[a-z]+
,如果:
这个词的结尾有[aieuo]
注意
我的答案并没有把字里行间保留下来。我想写一个Perl one liner,然后注意到@glenn jackman
已经这样做了。因此,您可以使用该答案或:
~ ❱ perl -lae' print for "@{[ grep{/\b(?![oauie])[a-z]+((?=[oauie]).)\b/} @F ]}" ' file
hello whatsi
hope worksa
ho
~ ❱
或不带“@{[…]}
运算符:
~ ❱ perl -lae '@arr = grep /\b(?![oauie])[a-z]+((?=[oauie]).)\b/, @F;print "@arr"' file
hello whatsi
hope worksa
ho
~ ❱
GNU awk用于多字符RS、RT和字边界:
$ gawk -v RS='\\<[^aeiou][[:alpha:]]*[aeiou]\\>' 'RT{print RT}' file
hello
whatsi
hope
worksa
ho
$gawk-vrs='\\''RT{print RT}'文件
你好
瓦茨
希望
工作
呵
如果需要保留原始换行符,则将GNU awk用于FPAT而不是RS将是:
$ gawk -v FPAT='\\<[^aeiou][[:alpha:]]*[aeiou]\\>' '{for (i=1; i<=NF; i++) printf "%s%s", $i, (i<NF?OFS:ORS)}' file
hello whatsi
hope worksa
ho
$gawk-v FPAT='\\'{for(i=1;i您可以指示grep
将输入视为一组以空字节结尾的行,即,如果您的输入不包含空字节,则使用-z
/--null data
标志将输入视为一条长行
这样,您就可以保留换行符(请注意,。| | \n
最后):
但代价是存在空字节(\x0
)字符(由于我们的正则表达式,还有多个空格)。这些可以用几个sed
表达式修复:
$ grep -Pozi '\b[bcdfghjklmnpqrstvwxyz]\w*[aeiou]\b| |\n' file \
| sed -E -e 's/\x0//g' -e 's/ +/ /g' -e 's/^ //' -e 's/ $//'
hello whatsi
hope worksa
ho
(一个用来去掉空字节,一个用来用一个空格替换多个空格,两个用来去掉前导空格和尾随空格)。这里有一个正则表达式来匹配以辅音开头、以元音结尾的单词
/\<[^ aeiouAEIOU]\w*[aeiouAEIOU]\>/
此shell命令将读取文件并将解析后的输出保存到out.txt
文件:
$ ex -s +'%s/\<\w\+\>\(\<[^ aeiouAEIOU]\w*[aeiouAEIOU]\>\)\@<!\s\?//g' +"%s/\([[:punct:]]\+\)//g" +%p +'wq! out.txt' test.txt
hello whatsi
hope worksa
ho
$ex-s+'%s/\\(\\)\@如果不…
是做…
呢?您希望在输出中看到做
还是不做?您需要包括“单词”的情况“如果在现实世界中可能出现这种情况,那么您的示例中不仅仅是空白,或者您将得到适用于您发布的示例输入但不适用于您的真实输入的解决方案。这忽略了问题的关键:OP已经知道grep-o
,但他希望保持行“完整”这不会像原始文件中那样保留换行符。我对grep
的回答是“向下投票”,而你对相同输出的回答是“向上投票:)我想是因为你出名了,而我不是。@k-five和Ed morton:你们给了我一个很好的笑声。顺便说一句,k-five和Ed对你们两个来说都是很好的解决方案。@glennjackman我现在更新了我的答案,谢谢你指出这一点。很高兴能帮上忙。毕竟,你就是Ed morton!;)如果目标单词没有被空格包围,则该操作将失败。请尝试将doesnt…
更改为do…
或好吧!
更改为示例输入中的we
。只有选择不当的示例输入/输出使其看起来有效。
$ grep -Pozi '\b[bcdfghjklmnpqrstvwxyz]\w*[aeiou]\b| |\n' file \
| sed -E -e 's/\x0//g' -e 's/ +/ /g' -e 's/^ //' -e 's/ $//'
hello whatsi
hope worksa
ho
/\<[^ aeiouAEIOU]\w*[aeiouAEIOU]\>/
$ printf "hello everyone, whatsi up\ni hope my program worksa\nif it doesnt... ho well!" > test.txt
$ ex -s +'%s/\<\w\+\>\(\<[^ aeiouAEIOU]\w*[aeiouAEIOU]\>\)\@<!\s\?//g' +"%s/\([[:punct:]]\+\)//g" +%p +'wq! out.txt' test.txt
hello whatsi
hope worksa
ho