如果打印出來$cmd
你設置後,你會看到這一點:
echo -e hello
world
...如果你粘貼到殼,你會得到類似的錯誤消息,雖然沒有-e
。
第一個問題是,當它到達shell時,該字符串缺少引號和非文字換行符。試試這個:
my $str = "hello\\nworld";
my $cmd = "echo -e '$str'";
在這種特殊情況下,你可以逃脫只是引號 - 將會有參數echo
內文字換行,但只要它引用了這是合法的。
但是,您仍然會在輸出中獲得立即數-e
,並且不會將\n
解釋爲換行符。這是因爲perl運行的是/bin/echo
,而不是內置於bash的echo
。如果你想使用bash的builtin,你必須告訴perl明確運行bash
。但這意味着將echo命令本身內部的參數傳遞給bash,從而引入另一個級別的引用來處理。
這裏最好的選擇是使用system
的多重參數版本;它繞過第一個shell級別並直接執行該命令。我們還必須應對新行:
my $str = "hello\nworld"; # literal newline
(my $escaped_str = $str) =~ s,\n,\\n,g; # escaped newline
爲了從殼獲得所需的行爲,我們需要嵌入在shell命令單引號括起來的,因爲在單引號裏的東西被認爲完全從字面上由殼。在這種情況下,我們只是從Perl代碼中的文字中分配字符串,所以我們知道它包含的內容,並且不包含撇號。但是,如果它可能永遠包含撇,我們應該運行它通過另一個逃生傳球給說出來了,所以它的安全在單引號嵌入:
$escaped_str =~ s,','\\'',g; # quote any embedded apostrophes
有可能是你希望與逃逸替換其他字符,太 - 也許標籤或回車。這將是進行這些更改的地方。
使用轉義字符串建立bash命令:
my $command = "echo -ne '$escaped_str'"; # bash command to echo string
手工做搜索/替換這樣很容易出錯;有很多邊緣案例需要考慮。所以,你可能也想看看CPAN模塊String::ShellQuote
,在其中您可以跳過手動上述逃逸,從原始這樣的轉義字符串:
my $command = shell_quote("echo", "-ne", $str);
一旦你有逃脫的命令字符串,請使用
system('bash', '-c', $command);
一般,更重要的是,我會考慮更換任何shell命令用Perl本身代碼的功能;:多參數system
直接與該字符串作爲參數運行的bash結果將更容易管理,並且可能更具可移植性和性能。
因爲'echo -e'不是可移植的,所以這是一個特別糟糕的例子。對於任何真實的東西,'echo'都可以做到,你可以在Perl中更簡單地做到這一點。也許你應該使用一個不同的例子,或許更接近你想要運行的真實代碼。 – tripleee