Regex grep/awk/perl/sed-打印所有与X匹配的行,忽略只有YX的行,并包括具有YX ZX的行

Regex grep/awk/perl/sed-打印所有与X匹配的行,忽略只有YX的行,并包括具有YX ZX的行,regex,perl,awk,sed,grep,Regex,Perl,Awk,Sed,Grep,我有一个文件(tmp.txt),看起来像: first first rst allrst printf“first\nfirst\nallrst\n”>tmp.txt 我想: first rst allrst 是否有任何方法可以搜索“rst”,但如果仅在第一个中找到rst,则排除匹配 我试过: awk '(/rst/ && /first/) || (/rst/ && !/first/)' tmp.txt ^(?=.*? 在Perl中试试这个。参见演

我有一个文件(tmp.txt),看起来像:

 first
 first rst
 allrst
printf“first\nfirst\nallrst\n”>tmp.txt

我想:

 first rst
 allrst
是否有任何方法可以搜索“rst”,但如果仅在第一个中找到rst,则排除匹配

我试过:

awk '(/rst/ && /first/) || (/rst/ && !/first/)' tmp.txt
^(?=.*?
在Perl中试试这个。参见演示


使用
grep
而不使用
-p
选项:

grep 'rst' file | grep -v '^first$'
first rst
allrst
使用
grep-p

grep -P '^(?!first$).*rst' file
first rst
allrst

还是vks答案的一个变体

^(.*(?<!fi)rst.*)$
^(.*?

^字符串的开头
(正在捕获组\1)
.除换行符外的任何字符
*(零或更多)(贪婪)

(?Perl中的正则表达式应该是
/^.*

^.*

(?您没有定义,因此
rst
必须位于行的末尾,因此这可能适用于您的要求:

grep -P '(?<!fi)rst' file
grep-P'(?

这可能适合您(GNU-sed):


制作当前行的副本。首先删除所有
,然后检查剩余行的
rst
。如果字符串位于更改的行中,则打印副本,否则删除该行。

这符合您的所有要求:

perl -ne 'print if /^(?=.*first)(?=.*(?<!fi)rst)/; next if /first/; print if /rst/'

perl-ne'print if/^(?=.*first)(?=)*(?I模式没有精确指定。如果行包含
affirst
rstffirst
,应该怎么做?因此我创建了两个版本。我假设每行包含字符串
rst
。不需要打印。我更喜欢使用解决方案,因为后者需要更多的资源来启动和打印此任务实际上不需要

第一个版本检查所有包含
rst
,但不等于
first
的单词。如果找到一个,则打印该行

awk '/rst/ {
  for(i=1;i<=NF&&$i~/rst/&&$i=="first";++i);
}i<=NF' inputfile
输出:

first rst
allrst
afirst
rstfirst
另一个解决方案检查所有
rst
,然后添加前两个字符(如果适用)。如果结果字符串不是
第一个
,则它将打印该行。(类似于
sln
的负查找缓冲区解决方案)

我希望这有点帮助

sed -n '1!{/rst/p}' tmp.txt
如果不在第一行,则打印与行中图案rst的匹配项,或者如果要单独计算rst而不是第一行-仅当rst也在另一个字符串中时:

sed -n '/[^f][^i]rst/p' tmp.txt 
或者,如果您想使用Bash shell,您可以更灵活地满足类似的要求:

while read -r a; do  
 num_first=$(echo "$a" | grep -c 'first');
 num_rst=$(echo "$a" | sed 's/first//g' | grep -c 'rst'); 
 if [[ $num_rst+1 -gt $num_first ]]; then 
   echo "$a"; 
 fi done < tmp.txt
读取时-ra;do
num_first=$(echo“$a”| grep-c“first”);
num_rst=$(回显“$a”| sed's/first//g'| grep-c'rst”);
如果[$num_rst+1-gt$num_first]];则
回音“$a”;
fi done
这段代码首先使用grep进行计数,然后使用rst-只有当rst的长度大于字符串的长度时,才会打印字符串

作为一个班轮:

read-ra;do num_-first=$(echo“$a”| grep-c'first”);num_-rst=$(echo“$a”| sed's/first//g'| grep-c'rst”);如果[$num_-rst+1-gt$num_-first]],则echo“$a”fi done

awk '/rst/ {
  for(i=1;i<=NF&&$i~/rst/&&$i=="first";++i);
}i<=NF' inputfile
first
first rst
allrst
afirst
rstfirst
first rst
allrst
afirst
rstfirst
awk '/rst/ {
  for(s=$0;i=index(s,"rst");s=substr(s,i+1)) 
    if (i<2 || substr(s,i-2,5)!="first") {print; break}
}' inputfile
first rst
allrst
rstfirst
sed -n '1!{/rst/p}' tmp.txt
sed -n '/[^f][^i]rst/p' tmp.txt 
while read -r a; do  
 num_first=$(echo "$a" | grep -c 'first');
 num_rst=$(echo "$a" | sed 's/first//g' | grep -c 'rst'); 
 if [[ $num_rst+1 -gt $num_first ]]; then 
   echo "$a"; 
 fi done < tmp.txt