簡體   English   中英

Perl轉義bash執行的參數

[英]Perl escaping argument for bash execution

我在Perl中編寫了一些代碼,它在執行過程中執行一些bash命令。 我的問題是當bash命令屬性包含空格時,bash命令執行失敗。 但我已經設法使用這些參數簡單地在參數周圍添加引號。 不幸的是在測試期間我發現我的腳本在\\字符放在變量的末尾時失敗,這明顯地逃脫了bash執行引用並且失敗了bash命令。 例如:

my $arg1 = 'This is sample text which can be put into variable. And a random sign\\';
`echo "$arg1"`

有沒有機會自動轉義變量中的特殊字符?

在bash中使用單引號要容易得多; 那么你需要擔心的唯一一個角色就是單引號本身。

($arbitrary_string) =~ s/'/'"'"'/g;

`echo '$arbitrary_string'`

CPAN來救援。

String :: ShellQuote應該做你需要的,盡管我同意@glennjackman system (或Capture :: Tiny )是一種更好的方法:

use String::ShellQuote 'shell_quote';

my $cmd = shell_quote( 'echo', 'This is sample text ending in a slash \\' );

`$cmd`;

不要使用反引號來保持你的字符串遠離shell,因此所有引用問題:

system 'echo', $var;

你寫:

不幸的是,我需要這個命令的stdout。 另一件事是變量用於lil bit complex命令,它使用了許多管道和東西: echo $var | sed | grep | awk | and so on... and so on... echo $var | sed | grep | awk | and so on... and so on...

您可能想要使用類似的東西進行調查(未經測試,主要來自IPC :: Open3 perldoc)

use IPC::Open3;
use Symbol 'gensym';

my ($wtr, $rdr, $err);
$err = gensym;
my $pid = open3($wtr, $rdr, $err, 'sed|grep|awk|and so on');
print $wtr $var;
close $wtr;
my $output = <$rdr>;
waitpid $pid, 0;

如果您的管道非常混亂,請將其存儲在shell腳本文件中,並從perl調用該腳本。

使用quotemeta

my $arg1 = quotemeta('string to be escaped');
`echo $arg1`

\\Q\\E (這正是quotemeta);

my $arg1 = 'string to be escaped';
`echo \Q$arg1\E`

另請注意,使用echo 是打印任意字符串的一種不好的方法

如果您使用的是quotemeta,請不要在參數周圍添加任何引號。

當直接從perl調用時,正如Glenn Jackman所說,我會使用systemexec來避免引用麻煩並捕獲輸出,例如計算文件的md5sum:

my $pid, $safe_kid; 
die "cannot fork: $!" unless defined ($pid = open($safe_kid, "-|"));
if ($pid == 0) {
   # This is the child process, exec md5sum
   exec('/usr/bin/md5sum', '--binary', $filename) or die "can't exec md5sum: $!";
} else {
   # This is the parent process, read data (we do not need to wait for
   # child process termination)
   @sum = <$safe_kid>;
   close $safe_kid; # $? contains status 
}
if ($?!=0) {
   die "Problem computing hashsums on '$filename': $!\n";
}

在相關的說明中,我一直在尋找一種方法來打印命令行參數到shell以供用戶復制和粘貼。 我想到了單引一切,並使用echo重新組合字符串,如果單引號已經存在,雖然使用String :: ShellQuote似乎是一個更好的主意,真的:

#!/usr/bin/perl

use strict;

testEscapeForBash("Hello World");
testEscapeForBash("Hello World!");
testEscapeForBash("Nothing_special_here.txt");
testEscapeForBash("With'One Single Quote");
testEscapeForBash("With 'Two Single' Quotes");
testEscapeForBash("'With Surrounding Single Quotes'");
testEscapeForBash("With \$ Dollar Sign");
testEscapeForBash("With * Fileglob");
testEscapeForBash("With ! History Expansion Sign");
testEscapeForBash("   ");
testEscapeForBash(" Some surrounding spaces ");

sub testEscapeForBash {
   my ($in) = @_;
   my $out = escapeForBash($in);
   print "[$in] gives\n       $out\n";
}

sub escapeForBash {
   my ($name) = @_;
   if (!$name) {
      die "Empty name passed to 'escapeForBash'"
   }
   my @parts = split(/'/,$name,-1); # limit is negative to catch trailing quote
   my $res;
   if (@parts == 1) {
      $res = "'$name'"
   }
   elsif (@parts > 1) {
      $res = '$(echo ';
      my $first = 1;
      for my $part (@parts) {
         $res .= "\"'\"" unless $first;
         $first = 0;
         $res .= "'";
         $res .= $part;
         $res .= "'";
      }
      $res .= ')';
   }
   else {
      die "Weird number of parts: @parts"
   }
   return $res
}

我們運行這個:

[Hello World] gives
       'Hello World'
[Hello World!] gives
       'Hello World!'
[Nothing_special_here.txt] gives
       'Nothing_special_here.txt'
[With'One Single Quote] gives
       $(echo 'With'"'"'One Single Quote')
[With 'Two Single' Quotes] gives
       $(echo 'With '"'"'Two Single'"'"' Quotes')
['With Surrounding Single Quotes'] gives
       $(echo ''"'"'With Surrounding Single Quotes'"'"'')
[With $ Dollar Sign] gives
       'With $ Dollar Sign'
[With * Fileglob] gives
       'With * Fileglob'
[With ! History Expansion Sign] gives
       'With ! History Expansion Sign'
[   ] gives
       '   '
[ Some surrounding spaces ] gives
       ' Some surrounding spaces '

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM