log*_*hee 71 grep sed text-processing
输入文件 1 是:
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
我给匹配的模式来自 in other file
(比如dog 123 4335
来自 file2)。
我匹配行的模式,dog 123 4335
并且在打印没有匹配行的所有行后,我的输出是:
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
如果只使用无行地址只使用模式,例如1s
如何匹配和打印行?
bra*_*zzi 48
在实践中,我可能大部分时间都使用Aet3miirah 的答案,而alexey 的答案对于浏览线条非常棒(而且,它适用于less
)。OTOH,我真的很喜欢另一种方法(这是一种颠倒的吉尔斯回答):
sed -n '/dog 123 4335/,$p'
Run Code Online (Sandbox Code Playgroud)
当使用-n
标志调用时,sed
默认情况下不再打印它处理的行。然后我们使用 2-address 形式,表示从匹配的行/dog 123 4335/
到文件末尾(由 表示$
)应用命令。有问题的命令是p
,它打印当前行。所以,这意味着“打印从匹配/dog 123 4335/
到结束的所有行”。
Tho*_*hor 35
假设您想将整行与您的模式匹配,使用 GNU sed
,这有效:
sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile
Run Code Online (Sandbox Code Playgroud)
标准等效:
sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile
Run Code Online (Sandbox Code Playgroud)
使用以下输入 ( infile
):
cat 13123 23424
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
输出是:
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
/^dog 123 4335$/
搜索所需的模式。:a; n; p; ba;
是一个循环,它从输入 ( n
)中获取一个新行,打印它 ( p
),然后分支回到标签 a :a; ...; ba;
。这是一个更接近您需求的答案,即文件 2 中的模式,从文件 1 中 grepping:
tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1
Run Code Online (Sandbox Code Playgroud)
嵌入的 grep 和 cut 从文件 2 中找到包含模式的第一行,此行号加一传递到尾部,加一用于跳过具有模式的行。
如果您想从最后一场比赛而不是第一场比赛开始,它将是:
tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1
Run Code Online (Sandbox Code Playgroud)
请注意,并非所有版本的 tail 都支持加号。
小智 33
如果您有一个相当短的文件grep
可能会起作用:
grep -A5000 -m1 -e 'dog 123 4335' animals.txt
Run Code Online (Sandbox Code Playgroud)
5000 只是我对“合理短”的猜测,因为grep
找到第一个匹配项并将其与接下来的 5000 行一起输出(文件不需要那么多)。如果您不想要匹配本身,则需要将其切断,例如
grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2
Run Code Online (Sandbox Code Playgroud)
tac animals.txt | sed -e '/dog 123 4335/q' | tac
Run Code Online (Sandbox Code Playgroud)
该行animals.txt
以行的相反顺序读取并输出直到并包括行,dog 123 4335
然后再次反转以恢复正确的顺序。
同样,如果您不需要结果中的匹配项,请附加尾部。(您也可以使 sed 表达式复杂化以在退出之前丢弃其缓冲区。)
Gil*_*il' 17
sed -e '1,/dog 123 4335/d' file1
Run Code Online (Sandbox Code Playgroud)
如果您需要从文件中读取模式,请将其替换为 sed 命令。如果文件包含 sed 模式:
sed -e "1,/$(cat file2)/d" file1
Run Code Online (Sandbox Code Playgroud)
如果文件包含要查找的文字字符串,请引用所有特殊字符。我假设该文件包含一行。
sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1
Run Code Online (Sandbox Code Playgroud)
如果您希望匹配是整行,而不仅仅是子字符串,请将模式包装在^…$
.
sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1
Run Code Online (Sandbox Code Playgroud)
小智 15
$ more +/"dog 123 4335" file1
Sté*_*las 11
与awk
:
awk 'BEGIN {getline pattern < "other file"}
NR == 1, $0 ~ pattern {next}; {print}' < "input file"
Run Code Online (Sandbox Code Playgroud)
如果输入是一个lseekable常规文件:
使用 GNU grep
:
{ grep -xFm1 'dog 123 4335' >&2
cat; } <infile 2>/dev/null >outfile
Run Code Online (Sandbox Code Playgroud)
与sed
:
{ sed -n '/^dog 123 4335$/q'
cat; } <infile >outfile
Run Code Online (Sandbox Code Playgroud)
grep
带有该-m
选项的GNU将在匹配时退出输入 - 它会在找到最后一个匹配点后立即离开其(lseekable)输入 fd。因此,调用grep
w/ 会-m1
在文件中找到模式的第一次出现,并将输入偏移量保留在正确的位置,cat
以便将文件中模式第一次匹配之后的所有内容写入标准输出。
即使没有 GNU,grep
您也可以在兼容 POSIX 的情况下做完全相同的事情sed
- 当sed
q
它被指定将其输入偏移量保留在正确位置时。但是,GNUsed
不符合标准,因此,sed
除非您使用其-u
开关调用它,否则上述内容可能无法与 GNU一起使用。
使用 awk 的一种方式:
awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}' file2 file1
Run Code Online (Sandbox Code Playgroud)
其中 file2 包含您的搜索模式。首先,file2 的所有内容都存储在数组“a”中。处理 file1 时,会根据数组检查每一行,并仅在不存在时打印。
小智 5
我对主题中问题的回答,没有将模式存储在第二个文件中。这是我的测试文件:
$ cat animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
GNU sed:
$ sed '0,/^dog 123 4335$/d' animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
珀尔:
$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
文件中带有模式的 Perl 变体:
$ cat pattern.txt
dog 123 4335
$ perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)
重量ed
:
ed -s file1 <<< '/dog 123 4335/+1,$p'
Run Code Online (Sandbox Code Playgroud)
这会p
在此处字符串中向 ed 发送一个 rint 命令;打印命令的范围限制为( )匹配后的1到文件末尾 ( )。+1
dog 123 4335
$