[英]Why is '$_' the same as $ARGV in a Perl one-liner?
我在嘗試在 Perl 單行中打印單引號時遇到了這個問題。 我最終發現你必須用'\\''
來逃避它們。 這是一些代碼來說明我的問題。
讓我們從打印文本文件開始。
perl -ne 'chomp; print "$_\n"' shortlist.txt
red
orange
yellow
green
blue
現在讓我們為每一行打印文件名。
perl -ne 'chomp; print "$ARGV\n"' shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
然后我們可以在每一行周圍添加單引號。
perl -ne 'chomp; print "'$_'\n"' shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
等等,沒有用。 讓我們再試一次。
perl -ne 'chomp; print "'\''$_'\''\n"' shortlist.txt
'red'
'orange'
'yellow'
'green'
'blue'
所以我現在開始工作了。 但我仍然對為什么 '$_' 計算為程序名稱感到困惑。 也許這很簡單,但有人可以解釋或鏈接到某些文檔嗎?
編輯:我在 Red Hat 5 上運行 Perl 5.8.8
對你的外殼, 'chomp; print "'$_'\\n"'
'chomp; print "'$_'\\n"'
結果是一個字符串的連接
chomp; print "
chomp; print "
(單引號內的第一個序列),$_
的值,以及\\n"
(單引號內的第二個序列)。 在bash
, $_
"... 擴展到上一個命令的最后一個參數,擴展后。..."。 由於這恰好是shortlist.txt
,因此將以下內容傳遞給perl
:
chomp; print "shortlist.txt\n"
例如,
$ echo foo
foo
$ echo 'chomp; print "'$_'\n"'
chomp; print "foo\n"
請注意,不應使用上述機制將值傳遞給 Perl 單行程序。 您不應該從 shell 生成 Perl 代碼。 請參閱如何在 -n 或 -p 模式下使用 Perl 處理選項? 了解如何為單行提供參數。
您在單行中使用單引號來保護您的 Perl 代碼不被 shell 評估。 在這個命令中:
perl -ne 'chomp; print "'$_'\n"' shortlist.txt
您關閉$_
之前的單引號,因此 shell 將$_
擴展到上一個命令的最后一個參數。 在您的情況下,這恰好是您輸入文件的名稱,但如果您先運行不同的命令,輸出會有所不同:
$ echo foo
$ perl -ne 'chomp; print "'$_'\n"' shortlist.txt
foo
foo
foo
foo
foo
正是出於這個原因,我盡量避免在一個班輪中使用引號。 當我可以時,我使用廣義引用:
% perl -ne 'chomp; print qq($_\n)'
雖然我可以避免使用-l
開關來免費獲得換行符:
% perl -nle 'chomp; print $_'
如果我不理解單行,我使用-MO=Deparse
來看看 Perl 認為它是什么。 前兩個是您期望的:
% perl -MO=Deparse -ne 'chomp; print "$_\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print "$_\n";
}
-e syntax OK
% perl -MO=Deparse -ne 'chomp; print "$ARGV\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print "$ARGV\n";
}
-e syntax OK
你在你看到問題的地方看到了一些有趣的東西。 該變量在perl
看到它之前就消失了,並且在它的位置有一個常量字符串:
% perl -MO=Deparse -ne 'chomp; print "'$_'\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print "shortlist.txt\n";
}
-e syntax OK
您的修復也很奇怪,因為Deparse將變量名稱放在大括號中以將其與舊的包說明符'
分開:
% perl -MO=Deparse -ne 'chomp; print "'\''$_'\''\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print "'${_}'\n";
}
-e syntax OK
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.