Perl to Bash: как символ перехода на новую строку "\ n" ведет себя особенным? - PullRequest
0 голосов
/ 26 февраля 2012

Когда я запускаю это без использования дополнительного escape-кода для "\n", hexdump не печатает 0a для встроенного перевода строки. Зачем "\n" нужна дополнительная обработка? (При поиске ответа я нашел String :: ShellQuote , который выполняет экранирование.)

#!/usr/bin/env perl
use warnings;
use 5.012;
use utf8;
binmode STDOUT, ':utf8';
use charnames qw(:full);
use IPC::System::Simple qw(system);

for my $i ( 0x08 .. 0x0d ) {
    printf "0x%02x - %s\n", $i, '\N{' . charnames::viacode( $i ) . '}';
    my $string = "It" . chr( $i ) . "s"; 
    $string =~ s/\n/\\n/g;
    system( "echo -e \Q$string\E | hexdump -C" );
    say "";
}

Ответы [ 2 ]

3 голосов
/ 26 февраля 2012

Если вы не преобразуете новую строку в два символа \n, вы выполняете команду

echo -e \
| hexdump -C

К sh, что эквивалентно

echo -e | hexdump -C

Когда вы переводите новую строку в два символа \n, вы выполняете команду

echo -e \\n | hexdump -C

, который передает два символа \n в echo, для которых выводит символ новой строки в -e.


Вам не нужно использовать -e и создавать побеги для -e. Вы можете создать правильную команду оболочки. Эта команда будет:

echo '
' | hexdump -C

Вы можете сделать это несколькими способами. Вы можете развернуть свое собственное решение.

(my $sh_literal = $string) =~ s/'/'\\''/g;
$sh_literal = "'$sh_literal'";
system( "echo $sh_literal | hexdump -C" );

Существует String :: ShellQuote .

use String::ShellQuote qw( shell_quote );
my $sh_literal = shell_quote($string);
system( "echo $sh_literal | hexdump -C" );

Наконец, вы можете полностью избежать оболочки.

open(my $fh, "|-", "hexdump", "-vC")
   or die("Could not start hexdump: $!\n");
print($fh $string);
1 голос
/ 26 февраля 2012

как прокомментировал @mugenkenichi, echo также интерпретирует ваши строки, поэтому вам придется экранировать специальные символы дважды, один раз для perl и один раз для echo.

Вместо этого такой подход может быть более удобным:

#!/usr/bin/env perl
use warnings;
use 5.012;
use utf8;
binmode STDOUT, ':utf8';
use charnames qw(:full);
use IPC::System::Simple qw(system);

for my $i ( 0x08 .. 0x0d ) {
    printf "0x%02x - %s\n", $i, '\N{' . charnames::viacode($i) . '}';
    my $string = "It" . chr($i) . "s";
    open( my $fh, "| hexdump -vC" )
      or die "could not talk to hexdump";
    print $fh $string;
    say "";
}
...