簡體   English   中英

為什么 '$_' 與 Perl one-liner 中的 $ARGV 相同?

[英]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"'結果是一個字符串的連接

  1. chomp; print " chomp; print " (單引號內的第一個序列),
  2. 其變量$_的值,以及
  3. \\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.

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