Eko neden alıntı karakterimi görmezden geliyor?


24

echoKomut bunu vermek tam metnini dahil değildir. Örneğin, yaparsam:

   $ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '

Çıktıları:

echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print } `

'Echo komutumda sahip olduğum tek tırnak ( ) dahil edilmedi. Çift tırnak işaretine geçersem:

$ echo " echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `  "

echohiçbir şey çıkarmaz! Neden ilk örnekte tek tırnakları dışlıyor ve ikincisinde hiçbir şey çıkmıyor? Tam olarak yazdıklarımın çıktısını almasını nasıl sağlayabilirim?


3
Burada neyi başarmaya çalıştığınızdan emin değilsiniz. Neden bir yankı ifadesini diğerine yerleştiriyorsunuz? Yoksa tam anlamıyla bir komut yazdırmaya mı çalışıyorsunuz (örneğin veya böyle bir şey)?
Andy Smith,

Eko çıktısını başka bir dosyaya

Ne yapmaya çalıştığını açıklamalısın. "Aşağıdaki metni eklemek istiyorum: '…' bir dosyaya."
MikeyB

2
Bunu 5 dakikadan beri düzenlemeye çalışıyorum ama istenen çıktının ne olduğunu ciddiye almıyorum. Düzenleme : Tamam, sanırım şimdi bir tahminim var, bu yüzden düzenlemeyi denedim. Neyi
kastediyorsan

1
@Michael - Wow - Düzenlemen için sana biraz temsilci verebilirsem, ben - güzel bir iş bu gerçekten harika bir soru yapma!
Randall

Yanıtlar:


33

Sizin kabuk tırnak yorumlayarak, hem edilir 've "onlar bile ulaşmadan, echo. Gereksiz bile olsa, sadece argümanımın yanına çift tırnak koyarım; Örneğin:

$ echo "Hello world"
Hello world

Bu yüzden, ilk örneğinizde, çıktınıza değişmez fiyat teklifi işaretlerini dahil etmek istiyorsanız, bunların kaçması gerekir:

$ echo \'Hello world\'
'Hello world'

Veya daha önce alıntı yapılan bir argüman içinde kullanılmaları gerekir (ancak aynı türden bir teklif olamaz veya yine de kaçmanız gerekir):

$ echo "'Hello world'"
'Hello world'

$ echo '"Hello world"'
"Hello world"

İkinci örneğinizde, dizginin ortasında bir komut ikamesi çalıştırıyorsunuz:

grep  $ARG  /var/tmp/setfile  | awk {print $2}

Başlayanlar $ayrıca kabuk tarafından özel olarak ele alınır - bunları değişken olarak görür ve yerine değerlerini koyar. Büyük olasılıkla bu değişkenlerin hiçbiri kabuğunuzda ayarlanmadığından, aslında sadece çalışır

grep /var/tmp/setfile | awk {print}

Yana grepsadece bir argüman görür, o argümanı için konum arama deseni size, ve veri okumak gerekir yer stdin'nin olduğunu, bu bloklar girişi için bekleyen böylece varsayar. Bu yüzden ikinci komutunuz sadece takılıyor gibi görünüyor.

Argümanı tek tek alıntıladığınızda (ilk örneğinizin neredeyse işe yaramasının nedeni budur) bu olmaz, bu nedenle istediğiniz çıktıyı almanın bir yoludur:

echo \'' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '\'

Ayrıca çift alıntı yapabilirsiniz, ancak $s'den kaçmanız gerekir, böylece kabuk onları değişkenler olarak çözmez, böylece geri kalanlar da kabuk komut komutunu derhal çalıştırmaz:

echo "' echo PARAM=\`  grep  \$ARG  /var/tmp/setfile  | awk '{print \$2}' \`    '"

7

Michael Mrozek'in cevabı bunu iyi bir şekilde anlattığı için girişimlerinizin neden bu şekilde davrandığı konusunda fazla ayrıntıya girmeyeceğim . Özetle, tek tırnak arasındaki herşey ( '…') kelimenin tam anlamıyla (ve ilk bilhassa yorumlanır 'işaretleri değişmez dize sonu), oysa `ve $aralarında kendi özel anlamlarını muhafaza "…".

Tek tırnak içinde alıntı yoktur, bu nedenle tek tırnaklı bir dize içine tek bir alıntı koyamazsınız. Ancak buna benzeyen bir deyim var:

echo 'foo'\''bar'

Bu baskılar foo'barbağımsız değişkeni için, echotek tırnaklı üç karakter dizisinin yapılmış footek bir karakter ile birleştirilmiş, '(karakteri koruyarak elde 'önceki yoluyla özel anlamı ile ilgili \tek tırnaklı üç karakter dizisine ile birleştirilmiş) bar. Bu yüzden, sahne arkasında gerçekleşen olay tam olarak bu olmasa da, '\''tek bir alıntı dizesinin içine tek bir alıntı eklemenin bir yolu olarak düşünebilirsiniz .

Karmaşık çok satırlı dizeleri yazdırmak istiyorsanız, buradaki belge daha iyi bir araçtır . Buradaki döküman iki karakterden ve <<ardından <<EOFmetnin satırlarından sonra satırın sonundaki işaretleyiciden sonra gelen bir karakterden oluşur . İşaretçi herhangi bir şekilde ( 'EOF'veya "EOF"veya \EOF"E" "OF" veya…) belirtilmişse, metin kelimenin tam anlamıyla yorumlanır ( 'sıradan bir karakter olması dışında, tek tırnakların içindeki gibi ). İşaretçi hiç alıntılanmadıysa, metin $\`özel durumlarını koruyarak çift ​​tırnaklı bir dizgede olduğu gibi yorumlanır (ancak "yeni satırlar tam anlamıyla yorumlanır).

cat <<'EOF'
echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `
EOF

1

Tamam, bu işe yarayacak: -

echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '

Burada test etmek: -

[asmith@yagi ~]$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '
 echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' ` 

0

Gilles'in burada bir belge kullanma önerisi gerçekten güzel ve hatta Perl gibi betik dilleri içinde bile çalışıyor. OP'nin konusuna verdiği cevaba dayanan spesifik bir örnek olarak,

use strict;
my $cmd = q#cat <<'EOF' # . "\n" .
          q#echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `# . "\n" .
          q#EOF# ;
open (my $OUTPUT, "$cmd |");
print $_ while <$OUTPUT>;
close $OUTPUT;

Verilmiş, bu örnek biraz tartışmalı, ancak SQL ifadelerini psql(yerine cat) göndermek için faydalı bir teknik olarak buldum .

(Herhangi bir alfanümerik olmayan olmayan boşluk karakteri yerine kullanılabileceğini Not #Yukarıdaki jenerik alıntı yapı içinde, ancak karma bu örnek için de öne gibiydi edilir ve olmayan bir yorum olarak kabul etmiştir.)


-1

Emrinizi alalım

$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '

ve önce sınırlayıcı olarak tırnak işareti olmayan boşluk kullanarak sözcüklere ayırın:

Arg[1]=“' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print”
Arg[2]=“$2}' `    '”

Daha sonra, parametre genişletme işlevini yapıyoruz: genişlet $…ancak içeride değil '…'. Yana $2boş (ayarlanana sürece aracılığıyla örneğin set -- …), boş bir dize ile değiştirilecektir.

Arg[1]=“' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print”
Arg[2]=“}' `    '”

Sonra, alıntıyı kaldır.

Arg[1]=“ echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print”
Arg[2]=“} `    ”

Bu argümanlar daha sonra, birbiri ardına basacak ve tek bir boşlukla ayrılacak olan yankıya iletilir.

“ echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print } `    ”

Bu adım adım talimatın gözlenen davranışı daha net göstereceğini umuyorum. Sorunu önlemek için, şu şekilde tek tırnaktan kaçın:

$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '

Bu, tek tırnaklı dize sona erecek, daha sonra kelimeye bir (kaçan) tek bir alıntı ekleyecektir, ardından sözcüğü parçalamadan yeni bir tek tırnaklı dize başlatacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.