J.Carter
J.Carter

Reputation: 331

perl one-liner to keep only desired lines

I have a text file (input.txt) like this:

NP_414685.4: 15-26, 131-138, 441-465
NP_418580.2: 493-500
NP_418780.2: 36-48, 44-66
NP_418345.2:
NP_418473.3: 1-19, 567-1093
NP_418398.2:

I want a perl one-liner that keeps only those lines in file where ":" is followed by number range (that means, here, the lines containing "NP_418345.2:" and "NP_418398.2:" get deleted). For this I have tried:

perl  -ni -e "print unless /: \d/" -pi.bak input.txt del input.txt.bak

But it shows exactly same output as the input file. What will be the exact pattern that I can match here? Thanks

Upvotes: 2

Views: 309

Answers (3)

zdim
zdim

Reputation: 66964

First, print unless means print if not -- opposite to what you want.

More to the point, it doesn't make sense using both -n and -p, and when you do -p overrides the other. While both of them open the input file(s) and set up the loop over lines, -p also prints $_ for every iteration. So with it you are reprinting every line. See perlrun.

Finally, you seem to be deleting the .bak file ... ? Then don't make it. Use just -i

Altogether

perl -i -ne 'print if /:\s*\d+\s*-\s*\d+/' input.txt

If you do want to keep the backup file use -i.bak instead of -i


You can see the code equivalent to a one-liner with particular options with B::Deparse (via O module)

Try: perl -MO=Deparse -ne 1 and perl -MO=Deparse -pe 1

Upvotes: 6

yoniyes
yoniyes

Reputation: 1030

This:

perl -ne 'print if /:\s*(\d+\s*-\s*\d+\s*,?\s*)+\s*$/' input.txt

Prints:

NP_414685.4: 15-26, 131-138, 441-465
NP_418580.2: 493-500
NP_418780.2: 36-48, 44-66
NP_418473.3: 1-19, 567-1093

I'm not sure if you want to match lines that are possibly like this:

NP_418580.2: 493-500, asdf

or this:

NP_418580.2: asdf

This answer will not print these lines, if given to it.

Upvotes: 1

Hynek -Pichi- Vychodil
Hynek -Pichi- Vychodil

Reputation: 26131

This way:

perl -i.bak -ne 'print if /:\s+\d+-\d/' input.txt

Upvotes: 2

Related Questions