如何修改多行模式?
How to modify mutiple lines pattern?
我在文件中有这样的东西:
....
sth
Q-[N1] your name?
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name?
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
我想在以 Q- 开头的行末尾添加 "last name"。
在 Perl 中是否可以做到这一点,sed
、awk
、grep
?
转换后的文件如下所示:
....
sth
Q-[N1] your name? **Jim**
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? **JUNE**
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
此解决方案实际上并不使用多行模式,而只是查找第一行(Q-... your name?
部分)并将接下来的两行加载到模式 space 中。然后它用简单的正则表达式对这个(三行)模式 space 进行一些替换以获得所需的输出。
sed '/^Q-\[N[[:digit:]]*\] your name?/ {
N
N
s/\( your name?\)\(.* Last name is *\)\(.*\)$/ ****/
}' < file
use strict;
use warnings 'all';
our @ARGV = 'name_is_joe.txt';
my $data = do {
local $/;
<>;
};
$data =~ s/^(Q-.+)(\n^A1-.+\n^A2-.+\bis\s+(.+)\n)/ /gm;
print $data
输出
....
sth
Q-[N1] your name? Jim
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? JUNE
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
或者单行
perl -0777 -pe 's/^(Q-.+)(\n^A1-.+\n^A2-.+\bis\s+(.+)\n)/ /gm' myfile
awk
救援! (有 tac)
$ tac file |
awk '/My Last name is/{n=$NF} /^Q-/{[=10=]=[=10=] FS "**"n"**"}1' |
tac
....
sth
Q-[N1] your name? **Jim**
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? **JUNE**
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
你可以先把换行符翻译成;
,然后用sed搜索替换;最后将 ;
翻译回换行符。请尝试:
cat temp | tr '\n' ';' | sed -r 's/(your\s+name\?)(;A1-[^-]*-My\s+Last\s+name\s+is\s+)(\w+)/ /g' | tr ';' '\n'
输出:
....
sth
Q-[N1] your name? Jim
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? JUNE
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
我在文件中有这样的东西:
....
sth
Q-[N1] your name?
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name?
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
我想在以 Q- 开头的行末尾添加 "last name"。
在 Perl 中是否可以做到这一点,sed
、awk
、grep
?
转换后的文件如下所示:
....
sth
Q-[N1] your name? **Jim**
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? **JUNE**
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
此解决方案实际上并不使用多行模式,而只是查找第一行(Q-... your name?
部分)并将接下来的两行加载到模式 space 中。然后它用简单的正则表达式对这个(三行)模式 space 进行一些替换以获得所需的输出。
sed '/^Q-\[N[[:digit:]]*\] your name?/ {
N
N
s/\( your name?\)\(.* Last name is *\)\(.*\)$/ ****/
}' < file
use strict;
use warnings 'all';
our @ARGV = 'name_is_joe.txt';
my $data = do {
local $/;
<>;
};
$data =~ s/^(Q-.+)(\n^A1-.+\n^A2-.+\bis\s+(.+)\n)/ /gm;
print $data
输出
....
sth
Q-[N1] your name? Jim
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? JUNE
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
或者单行
perl -0777 -pe 's/^(Q-.+)(\n^A1-.+\n^A2-.+\bis\s+(.+)\n)/ /gm' myfile
awk
救援! (有 tac)
$ tac file |
awk '/My Last name is/{n=$NF} /^Q-/{[=10=]=[=10=] FS "**"n"**"}1' |
tac
....
sth
Q-[N1] your name? **Jim**
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? **JUNE**
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....
你可以先把换行符翻译成;
,然后用sed搜索替换;最后将 ;
翻译回换行符。请尝试:
cat temp | tr '\n' ';' | sed -r 's/(your\s+name\?)(;A1-[^-]*-My\s+Last\s+name\s+is\s+)(\w+)/ /g' | tr ';' '\n'
输出:
....
sth
Q-[N1] your name? Jim
A1-My first name is Joe
A2-My Last name is Jim
sth
sth
....
....
sth
Q-[N2] your name? JUNE
A1-My first name is Jack
A2-My Last name is JUNE
sth
sth
....