2010-07-09 72 views

回答

30

String::ShellQuote,但大多數時候這是不需要的。您可以通過仔細編程來避免調用shell。例如,system takes a list of arguments而不是字符串。

最佳實踐:

use IPC::System::Simple qw(systemx); 
systemx($command, @arguments); 

require IPC::System::Simple; 
use autodie qw(:all); 
system([@allowed_exit_values], $command, @arguments); 
+5

是的,就避免了殼完全如果在所有可能的。 – 2010-07-09 11:49:44

+3

用適當的解決方案回答[XY問題](http://www.perlmonks.org/index.pl?node_id=542341)的好工作。 :) – Ether 2010-07-09 15:07:08

+0

這可以幫助,但當你需要重定向(所以不能使用系統()調用的列表形式)*和*變量參數?例如一個解決以下失敗的嘗試'ls'f o o''的方法:'my $ foo ='f o o';我的$結果= \'ls $ foo 2> &1\';'? – artfulrobot 2014-04-23 11:04:49

3

Perl可以匹配以下功能:

增加將字符串和報價單引號/逃脫任何現有的單引號

http://php.net/manual/en/function.escapeshellarg.php#function.escapeshellarg

這樣的:

sub php_escapeshellarg { 
    my $str = @_ ? shift : $_; 
    $str =~ s/((?:^|[^\\])(?:\\\\)*)'/$1'\\''/g; 
    return "'$str'"; 
} 
+1

這不起作用。考慮將字符串「foo'bar」傳遞給函數。它會產生以下字符串:''foo \'bar''。但在單引號內不能有單引號。 – josch 2016-04-23 09:54:12

0

我有@daxim同意。但是在某些情況下,您不能像使用套接字將命令傳遞給不是perl的程序或沒有可用的IPC模塊那樣使用它。我也看了@axeman給出的正則表達式,這對我來說似乎有點複雜。我可能是錯的,但我認爲你不需要在單引號字符串中爲一個命令避開反斜槓。所以,你可以這樣做:

sub escapeshellarg { 
    my $arg = shift; 

    $arg =~ s/'/'\\''/g; 
    return "'" . $arg . "'"; 
} 

如果任何人有任何理由,爲什麼這可能是不安全的,我想知道。我已經使用任何可以想到使外殼執行任意代碼而沒有成功的欺騙來測試它,這使我認爲這個正則表達式與PHP實現相同。

在PHP實現中,它聲明它所做的只是:圍繞字符串添加單引號,引號/轉義任何現有的單引號。

這是這個正則表達式唯一的東西。 想法?

+2

我很懷疑,我總是更喜歡cagedtesters驗證的[String :: ShellQuote](http://p3rl.org/String::ShellQuote),它已經在野外部署了多年,並且有錯誤報告和修復程序通過SO用戶的ad-hoc正則表達式來顯示它。你可以將它的代碼與你的代碼進行比較,並找出你自己缺乏的東西。 – daxim 2012-05-28 14:46:51

+0

@daxim他們不太容易比較:http://api.metacpan.org/source/ROSCH/String-ShellQuote-1.04/ShellQuote.pm – dlamblin 2012-10-16 15:17:23

+0

該死,對不起,我不小心downvoted你的答案,現在我無法撤消它。 :( – josch 2016-04-23 10:03:03

1

這一個適用於我在BASH:

sub escape_shell_param($) { 
    my ($par) = @_; 
    $par =~ s/'/'"'"'/g; # "escape" all single quotes 
    return "'$par'";  # single-quote entire string 
} 

它是基於從BASH手冊頁採取了以下聲明:

  1. 在單引號圍護字符保留的字面意義引號內的每個字符。
  2. 單引號之間可能不會出現單引號,即使前面帶有反斜槓。
  3. 用雙引號括起來的字符保留了引號中所有字符的字面值,除了$,`, \,並且當啓用歷史擴展時!!

From(2。)我們知道反斜槓不能用於轉義單個qoutes,但是從(3)中可以看出,雙引號保留了(又名轉義)單引號的文字值。

還要注意的是報價的唯一目的是改變引用的字符的含義(不創建特殊的字符串對象或類似的東西)和擴張畢竟連續的文字字符連接在一起。然後,'foo''bar'foobar相同。

上面的函數做了什麼是單引號整個字符串,以便沒有特殊含義的字符。但是,爲了允許存在單引號字符,字符串會在發現此類字符的任何位置被拆分,並執行以下操作:前一個子字符串已完成('),然後引入一個雙引號單引號("'")並開始下一個子字符串(')。這就是爲什麼'全球取代'"'"'

例如(僞代碼):

foo'bar => 'foo' + "'" + 'bar'