![](/img/trans.png)
[英]awk/sed/grep/perl using field separator then only showing specific lines
[英]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
或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/'
或者,如您的標題所示,象征性地
perl -ne '
BEGIN {$x="rst"; $y="fi"; $z="(?<!fi)"}
print if /^(?=.*$y$x)(?=.*$z$x)/; next if /$y$x/; print if /$x/
'
恕我直言,該模式沒有精確指定。 如果該行包含afirst
或rstfirst
怎么rstfirst
? 所以我創建了兩個版本。 我假設每一行都包含字符串rst
。 不需要,則不需要打印。 我更喜歡awk解決方案而不是perl,因為后者會使用更多的資源來啟動,並且實際上並不需要此任務。
第一個版本檢查所有包含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
的負向后緩沖perl解決方案)
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.