在 perl 中读取标准输入需要在输入周围换行。如何避免?

Reading stdin in perl requires line feeds around input. How to avoid?

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{}/g; print; }'

此 perl 单行代码将标记换成转义序列。
它按预期工作,但前提是输入被换行包围。

echo "\x0a${MSG_OUT}\x0a" | perl -ne '.... etc.

从标准输入读取时如何避免这个问题?

-n 将您的代码包装在 while (<>) { ... }* 中(参见 perldoc perlrun)。因此,您的一行相当于:

perl -e '
   while(<>) {
      %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m");
      while (<>) { s/(<([BINORSU])>)/\e$ES{}/g; print; }
   }
'

[为便于阅读添加了换行符。如果您愿意,可以删除它们。]

看到双while (<>) { ... }了吗?那是你的问题:第一个 while (由 -n 添加的)读取一行,然后第二个 while (你写的那个)读取第二行,你的 s///(在第二行),并打印第二行已更新。因此,您需要在要处理的实际行之前有一个空行。

要解决此问题,请删除内部 while(<>),或删除 -n 标志。例如:

perl -e '
   %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m");
   while (<>) { s/(<([BINORSU])>)/\e$ES{}/g; print; }
' 

或者,

perl -ne '
   BEGIN { %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m") };
   s/(<([BINORSU])>)/\e$ES{}/g; print;
'

请注意,您可以使用 -p 而不是使用 -nprint,这与 -n 相同,但多了一个 print* * 最后:

perl -pe '
    BEGIN { %ES=("B","[1m","I","[3m","N","[m","O","[9m","R","[7m","U","[4m") };
    s/(<([BINORSU])>)/\e$ES{}/g;
'

* 为了完整起见,请注意 -nwhile 循环 (LINE: while(<>) { ... }) 之前添加了标签 LINE,尽管这并没有你的情况很重要。

** -p 添加的 print 实际上在 while 之后的 continue 块中,虽然,再一次,这并不跟你的情况没关系。