问题
I have a file called test.txt with the following:
> Last login: Mon Jul 13 05:09:33 2020 You have mail.
> ******************************
> cat, you have just logged into machine sampleserver2
> ******************************
>
> --------------------------------------------------------------
> | To switch environments later, run: |
> | |
> | change |
> | |
> --------------------------------------------------------------
>
>
> Current Dir => /apps/users/cat Oracle SID: SAMPLE
> cat@sampleserver2:
I try running the command below to only return the last colon but it returns the full line. To my understanding it should only be returning the : and not cat@sampleserver2:. What am I doing wrong? I'm also using a version of Perl that should be able to handle this.
cat test.txt | perl -ne 'print if /.+@.+\K:/'
cat@sampleserver2:
% perl -v
This is perl 5, version 30, subversion 1 (v5.30.1) built for
x86_64-linux-ld
回答1:
You may want to say:
perl -ne 'print $& if /.+@.+\K:/' test.txt
which outputs:
:
- The statement
print if CONDITIONis equivalent toprint $_ if CONDITIONand just prints the line without modifications if the CONDITION meets. Please use$&instead. - The second argument
cat@sampleserver2:will cause an error saying "Can't open cat@sampleserver2:: No such file or directory."
回答2:
The \K ignores part of the match so it doesn't show up in $& (or the part of the string that s/// will replace. But, you output $_, the default variable that print uses when you give it no argument.
I don't know why you want to return the last colon. If you know that you are only going to output the colon, you don't need fancy regex features. Match the line then output the known string:
print ':' if /.+\@.+:/
But I suspect you are actually trying to do something else. Are you trying to skip the login banner and capture whatever is after the first command-line prompt?
Also, you one-liner looks suspicious. You have:
cat test.txt | perl -ne 'print if /.+@.+\K:/' cat@sampleserver2:
That cat@sampleserver2: is a command-line argument and the implicit while(<>){...} from the -n switch will try to open a file with that name and read it. Maybe you have a file named that. That filename isn't the target for the match operator, but I suspect you think it is.
But, if you have a file with that name, why are you also piping another file? You don't need the cat there. This will read through lines of test.txt:
% perl -ne 'print if /.+@.+\K:/' test.txt
来源:https://stackoverflow.com/questions/62886586/why-is-perl-regex-k-not-excluding-the-pattern-matched-before-k