IFS = $ '\ n' kelimesinin tam anlamı nedir?


125

IFSOrtam değişkenini bir satır besleme karakterine ayarlayan aşağıdaki örnek ...

IFS=$'\n'
  • Dolar işareti tam olarak ne anlama geliyor ?
  • Bu özel durumda ne yapar?
  • Bu özel kullanım hakkında nereden daha fazla bilgi edinebilirim (Google aramalarda özel karakterlere izin vermez ve başka türlü ne arayacağımı bilmiyorum)?

IFSOrtam değişkeninin ne olduğunu ve \nkarakterin (satır beslemesi) ne olduğunu biliyorum , ancak neden sadece şu biçimi kullanmıyoruz: IFS="\n"(hangisi çalışmıyor)?

Örneğin, bir dosyanın her satırında döngü yapmak ve bir for döngüsü kullanmak istersem, şunu yapabilirim:

for line in (< /path/to/file); do
    echo "Line: $line"
done

Ancak, IFSbir satır besleme karakterine ayarlanmadıkça bu doğru çalışmayacaktır . Çalışması için şunu yapmalıyım:

OLDIFS=$IFS
IFS=$'\n'
for line in (< /path/to/file); do
    echo "Line: $line"
done
IFS=$OLDIFS

Not: Aynı şeyi yapmak için başka bir yola ihtiyacım yok, zaten başka birçok şeyi biliyorum ... Bunu sadece merak ediyorum $'\n've birinin bana bununla ilgili bir açıklama yapıp yapamayacağını merak ediyorum.

Yanıtlar:


161

Normalde bashdizge değişmezlerinde kaçış dizilerini yorumlamaz. Yani, \nveya "\n"veya yazarsanız '\n', bu bir satır sonu değildir - bu bir harftir n(ilk durumda) veya bir ters eğik çizgi ve ardından bir harf gelir n(diğer iki durumda).

$'somestring'kaçış dizileri ile dize değişmezleri için bir sözdizimidir . Bunun aksine '\n', $'\n'aslında bir satır sonu.


2
Tam olarak öyle değil - \nsadece (kaçan) bir harftir n. Haklısın '\n've "\n"geri tepme ve ardından n.
Roman Cheplyaka

15
Bunun $'\n'bash'a özgü olduğuna dikkat edin - bir POSIX kabuğunda ( /bin/sh) çalışmayacaktır. Aynı etkiyi POSIX uyumlu bir şekilde elde etmek için, yazabilir IFS=', ardından gerçek bir satırsonu karakteri yazmak için return tuşuna basabilir , ardından kapanışı yazabilirsiniz'
Richard Hansen

23
IFS=$(echo -e '\n')POSIX uyumlu bir şekilde de yapmalıdır.
Vineet

12
@Vineet - olumlu oy verilen bir yoruma itiraz etmeme ara verdi. Bu ise bir Posix-doğru, değil çalışır - bash komut ikamesi operatörleri tüm sondaki yeni satır karakterleri kaldırın. Daha fazla ayrıntı için buna bakın .
Dijital Travma

9
: @DigitalTrauma ben bile POSIX olmadığını düşünüyorum -etanımlı değil ve \nolmayan -ebir XSI uzantısı olarak işler: pubs.opengroup.org/onlinepubs/9699919799/utilities/... . printf '\n'kayalar;)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

21

Sadece yapıya resmi adını vermek için : formun dizeleri ANSI C-alıntı dizeleri$'...' olarak adlandırılır .

Yani, [ANSI] C dizelerinde olduğu gibi, geri tepme kaçış dizileri tanınır ve gerçek eşdeğerlerine genişletilir (desteklenen kaçış dizilerinin tam listesi için aşağıya bakın).

Sonra bu genişleme, $'...'aynı şekilde davranmasına dizeleri '...'dizeleri - yani onlar gibi muamele ediyoruz değişmezleri herhangi [daha fazla] kabuk açılımları için DEĞİL konu .

Örneğin, $'\n'değişmez bir satırsonu karakterine genişler - bu, normal bir bash dizesi değişmezinin (olsun '...'veya olmasın "...") yapamayacağı bir şeydir . [1]

Bir başka ilginç özellik ise, ANSI C'den alıntılanan dizelerin kaçabilmesidir '(tek tırnak)\' , '...'(normal tek tırnaklı dizeler):

echo $'Honey, I\'m home' # OK; this cannot be done with '...'

Desteklenen kaçış dizilerinin listesi :

Varsa ters eğik çizgi kaçış dizilerinin kodu şu şekilde çözülür:

\ bir uyarı (zil)

\ b geri tuşu

\ e \ E bir çıkış karakteri (ANSI C değil)

\ f form beslemesi

\ n yeni satır

satır başı

\ t yatay sekme

\ v dikey sekme

\ ters eğik çizgi

\' tek alıntı

çift ​​tırnak

\ nnn değeri sekizlik değer nnn (bir ila üç basamak) olan sekiz bitlik karakter

\ xHH değeri onaltılık değer HH olan sekiz bitlik karakter (bir veya iki onaltılık rakam)

\ uHHHH Değeri onaltılık HHHH değeri olan Unicode (ISO / IEC 10646) karakteri (bir ila dört onaltılık basamak)

\ UHHHHHHHH Değeri onaltılık HHHHHHHH (bir ila sekiz onaltılık basamak) olan Unicode (ISO / IEC 10646) karakteri

\ cx bir kontrol-x karakteri

Genişletilmiş sonuç, dolar işareti yokmuş gibi tek tırnaklıdır.


[1] Bununla birlikte, gerçek yeni satırları '...' ve "..." dizelerine gömebilirsiniz ; yani, birden çok satıra yayılan dizeler tanımlayabilirsiniz.



8

Varsayılan IFS'yi yeniden kurtarma - bu OLDIFS=$IFSgerekli değildir. Varsayılan IFS'yi geçersiz kılmamak için alt kabukta yeni IFS çalıştırın:

ar=(123 321); ( IFS=$'\n'; echo ${ar[*]} )

Ayrıca eski IFS'yi tam olarak kurtardığına gerçekten inanmıyorum. Gibi satır kırılmasını önlemek için çift tırnak almalısınız OLDIFS="$IFS".


2
bu gerçekten kullanışlı bir tekniktir. ben sadece daha temiz bir kabuk için kullanılan op katılmak: args=$(IFS='&'; echo "$*"). geri IFSiçin $' \t\n'bir Bourne kabuğu dost bir şekilde yok demek feat.
jeberle

Re Besides I don't really believe you recover the old IFS fully: sözcüklere ayırma edilir değil değişken atamaları RHS üzerinde gerçekleştirilen (ama alıntı çıkarılmasıdır), bu yüzden OLDIFS=$IFSve OLDIFS="$IFS"aynı şekilde davranır.
mklement0

3

ANSI C'den alıntılanan dizeler kilit noktadır. @ Mklement0'a teşekkürler.

ANSI C'den alıntılanan dizeleri od komutuyla test edebilirsiniz.

echo -n $'\n' | od -c
echo -n '\n' | od -c
echo -n $"\n" | od -c
echo -n "\n" | od -c

Çıktılar:

0000000  \n  
0000001

0000000   \   n   
0000002

0000000   \   n   
0000002

0000000   \   n   
0000002

Anlamını çıktılardan açıkça bilebilirsiniz.


-7

Değeri bir değişkenden almak gibi:

VAR='test'
echo VAR
echo $VAR

farklıdır, bu nedenle dolar işareti temelde içeriği değerlendirir.


6
Bunun değişkenlerle ilgisi yok. $'FOO'( $FOObunun hakkında soru olmadığından farklı olarak) bir dize değişmezidir. Yürütürseniz echo $'VAR'o dizeyi yazdıran o görürsünüz VARdeğil test.
sepp2k
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.