簡體   English   中英

grep / awk / perl / sed-打印所有與X匹配的行,忽略僅具有YX的行,並包括具有YX ZX的行

[英]grep / awk / perl / sed - print all lines that match X, ignore lines that only have YX and include lines that have YX ZX

我有一個文件(tmp.txt)看起來像:

 first
 first rst
 allrst

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

而且我要:

 first rst
 allrst

有什么方法可以搜索“ rst”,但是如果僅在第一個中找到rst,則排除匹配項?

我試過了:

awk '(/rst/ && /first/) || (/rst/ && !/first/)' tmp.txt

使用不帶-P選項的grep

grep 'rst' file | grep -v '^first$'
first rst
allrst

使用grep -P

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

在Perl中嘗試一下。

http://regex101.com/r/kP8uF5/13

或vks答案的變化

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

演示

^               Start of string
(               Capturing Group \1
  .             Any character except line break
  *             (zero or more)(greedy)
  (?<!          Negative Look-Behind
    fi          "fi"
  )             End of Negative Look-Behind
  rst           "rst"
  .             Any character except line break
  *             (zero or more)(greedy)
)               End of Capturing Group \1
$               End of string

Perl中的正則表達式為/^.*(?<!fi)rst.*/m

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

您沒有定義它,第rst必須在行的末尾,因此這可以滿足您的要求:

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

這可能對您有用(GNU sed):

sed 'h;s/first//g;/rst/!d;g' file

復制當前行。 刪除所有first ,並檢查剩余的行是否為rst 如果字符串在更改的行中,則打印副本,否則刪除該行。

這符合您的所有要求:

perl -ne 'print if /^(?=.*first)(?=.*(?<!fi)rst)/; next if /first/; print if /rst/'
  1. 行具有“第一”和非第一“ rst”:打印它
  2. 行具有“第一”:跳過它
  3. 行具有“ rst”:打印它

或者,如您的標題所示,象征性地

perl -ne '
  BEGIN {$x="rst"; $y="fi"; $z="(?<!fi)"}
  print if /^(?=.*$y$x)(?=.*$z$x)/; next if /$y$x/; print if /$x/
'

恕我直言,該模式沒有精確指定。 如果該行包含afirstrstfirst怎么rstfirst 所以我創建了兩個版本。 我假設每一行都包含字符串rst 不需要,則不需要打印。 我更喜歡解決方案而不是因為后者會使用更多的資源來啟動,並且實際上並不需要此任務。

第一個版本檢查所有包含rst但不等於first單詞。 如果找到,則打印該行。

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

另一種解決方案是檢查所有rst ,然后添加前兩個字符(如果適用)。 如果結果字符串不是first那么它將打印該行。 (類似於sln的負向后緩沖解決方案)

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

如果不在第一行,則在該行中打印與模式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

此代碼先使用grep先計數,然后再使用rst計數-僅當rst大於字符串的首位時,它才會打印字符串。

作為單線:

while read -ra; 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 < myfile

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM