MSG_OUT="<B><I>Skipping<N> all libraries and fonts...<N>"
perl -ne '%ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m"); while (<>) { s/(<([BINORSU])>)/\e$ES{$2}/g; print; }'
This perl one-liner swaps a token for an escape sequence.
It works as intended but only if the input is surrounded with line feeds.
ie
echo "\x0a${MSG_OUT}\x0a" | perl -ne '.... etc.
How do I avoid this issue when reading from stdin?
-n
wraps your code in while (<>) {... }
* (cf perldoc perlrun ). Thus, your one-liner is equivalent to:
perl -e 'while(<>) { %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m"); while (<>) { s/(<([BINORSU])>)/\e$ES{$2}/g; print; } }'
See the double while (<>) {... }
? That's your issue: the first while
(the one added by -n
) reads a line, then the second while
(the one you wrote) reads a second line, does your s///
(on the second line), and prints this second line updated. Thus, you need a blank line before the actual line you want to process.
To fix the issue, either remove the inner while(<>)
, or remove the -n
flag. For instance:
perl -e '%ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m"); while (<>) { s/(<([BINORSU])>)/\e$ES{$2}/g; print; }'
Or,
perl -ne 'BEGIN { %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m") }; s/(<([BINORSU])>)/\e$ES{$2}/g; print;'
Note that instead of using -n
and print
, you can use -p
, which is the same as -n
with an extra print
** at the end:
perl -pe 'BEGIN { %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m") }; s/(<([BINORSU])>)/\e$ES{$2}/g;'
* For completness, note that -n
adds the label LINE
before the while
loop ( LINE: while(<>) {... }
), although that doesn't matter in your case.
** The print
added by -p
is actually in a continue
block after the while
, although, once again, this doesn't matter in your case.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.