在 Perl 中读取 stdin 需要在输入周围换行。如何避免?

YMO*_*MOZ 5 perl

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; }'
Run Code Online (Sandbox Code Playgroud)

这个 Perl 单行代码将标记替换为转义序列。
它按预期工作,但前提是输入被换行符包围。

IE

echo "\x0a${MSG_OUT}\x0a" | perl -ne '.... etc.
Run Code Online (Sandbox Code Playgroud)

从 stdin 读取时如何避免此问题?

Dad*_*ada 4

-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{$2}/g; print; }
   }
'
Run Code Online (Sandbox Code Playgroud)

[添加换行符以提高可读性。如果您愿意,可以将它们删除。]

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

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

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

或者,

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

请注意,您可以使用,而不是使用-nand ,这与末尾额外的**相同:print-p-nprint

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

*为了完整性,请注意在循环 ( )之前-n添加标签,尽管这在您的情况下并不重要。LINEwhileLINE: while(<>) { ... }

**添加print-p实际上是在continue后面的块中while,尽管这对于您的情况来说并不重要。