“#! / Bin / sh -a” içindeki -a neden sed'i etkiler ve “set -a” etkilemez?


20

Aşağıdaki .sh dosyasını çalıştırırsam:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Sonuç bir hatadır:

sed: -e ifade # 1, karakter 18: Geçersiz aralık sonu

Ancak aşağıdaki .sh dosyasını çalıştırırsam:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Hatasız çalışır. İkinci kod ilk kodla eşdeğer değil mi? Neden ilk hata?


Hepsi shaynı değil. Ne de tüm sed eşdeğerdir. Hangisini shkullanıyorsun? Hangi işletim sisteminde? ve Hangi sed (belki? sed --versionbaşarısız değilse)?
Isaac

1
sorun etrafında çalışmak için çağrı ayarı LC_COLLATE=C(veya POSIX)sed
Jeff Schaller

4
Bulduğum bir fark: ilk komut dosyası POSIXLY_CORRECT=yortamda sed (ve muhtemelen başka bir yardımcı program) çağırıyor , ikincisi POSIXLY_CORRECTortamda yok. Her iki komut dosyasını da çağırdığım kabuğun POSIXLY_CORRECTçevresinde yok.
Mark Plotnick

1
Ah, echo "a" | POSIXLY_CORRECT=y sed -e 's/[\d001-\d008]//g' sorununu yeniden
Isaac

1
Yukarıdakilerin OP'nin CentOS 7.x - GNU bash, sürüm 4.2.46 (2) -çalışması (x86_64-redhat-linux-gnu) ve CentOS Linux yayın 7.5.1804'te (Core) gösterdiği gibi benim için başarısız olduğunu doğrulamak .
slm

Yanıtlar:


31

Bash adıyla çağrıldığında shbunu yapar :

if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
    act_like_sh++;

ve daha sonra shell değişkenini şu şekilde ayarlarPOSIXLY_CORRECTy :

if (act_like_sh)
  {
    bind_variable ("POSIXLY_CORRECT", "y", 0);
    sv_strict_posix ("POSIXLY_CORRECT");
  }

bind_variablearamalar bind_variable_internal, hangi kabuk niteliği ise a(eğer birlikte kabuk çağrılan eğer olacağını anda açık -a), işaretleri olarak kabuk değişkeni ihraç .

İlk betiğinizde:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

sedile çağrılır POSIXLY_CORRECT=yonu şikayet yapacak çevresiyle, içinde [\d001-\d008]. (Sed --posixseçeneğine sahipse aynı şey olur .)

GNU sed olarak, sayısal değer olarak bir karakter için bir çıkış kodu olan bir baz-10 NNN , ancak POSIX modunda, bu yüzden bir dirsek ifade içinde devre dışı , kelimenin tam anlamıyla araçlar karakterler , aralık ise, vs. için . Karakter kodları sırasına göre önce gelir (ve aralık, sıfır hariç tüm rakamları, ayrıca tüm büyük harfleri ve bazı özel karakterleri içerir). Gelen kullanmakta olduğunuz yerel ayarı, daha önce sıralar aralığı geçersiz böylece Ancak.\dNNN[\d001-\d008]\d1\1\en_US.UTF-8\1

İkinci komut dosyanızda:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

POSIXLY_CORRECTKabukta ayarlanmış olmasına rağmen , dışa aktarılmaz, bu nedenle sed POSIXLY_CORRECTortamda olmadan çağrılır ve sed GNU uzantılarıyla çalışır.

export POSIXLY_CORRECTİkinci senaryonuzun üst kısmına eklerseniz sed şikayetini de görürsünüz.


6
Bana göre, bu bir hata.
Stéphane Chazelas

1
kutsal kabuk dehşeti, Batman! Bu ilginç bir tuhaflık (ve /bin/shaslında Bash olmaktan kaynaklanan bir sorunu görmek için biraz değişiklik ). Aynı şey Bash başlamadan POSIXLY_CORRECTönce ortamdaysa da olur sh: aynı zamanda olarak da iletilir POSIXLY_CORRECT=y.
ilkkachu

3
@StevenPenny ama POSIXLY_CORRECT değil kabuk başlar ve senaryo olarak ayarlayın vermediğinde ortamda. Kabuk yapar. Hiçbir yerden bir ortam değişkeni yaratır; bu, olması gerektiği bir modda yaptığı için çok kötüdür ve standart uyumlu olmaya çalışır.
ilkkachu

4
FWIW, Bash ayrıca POSIXLY_CORRECTkendi başına belirleyeceğini de belgelemiyor . POSIX modunun efektleri listesinde bundan bahsedilmiyor ve değişken açıklaması sadece kabuğun ayarının tersine değil POSIX moduna değiştirdiğini söylüyor.
ilkkachu

1
@ilkkachu. Bitti. POSIX spesifikasyonunun hangi değişkenlerden etkilendiğini netleştirmek için güncellenmesi gerektiğini düşünüyorum allexport.
Stéphane Chazelas
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.