Mawk'de kendi script adını nasıl yazdırabilirim?


13

Bash $0betiğin adını içerir, ancak awk içinde aşağıdaki içeriğe sahip myscript.awk adlı bir komut dosyası yaparsam:

#!/usr/bin/awk -f
BEGIN{ print ARGV[0] }

ve çalıştırın, sadece "awk" yazdıracaktır. Ayrıca, i> 0 ile ARGV [i] yalnızca komut satırındaki kod bağımsız değişkenleri için kullanılır. Peki, bu durumda "myscript.awk" komut dosyasının adını yazdırmak nasıl?


Tüm çözümler gawk gerektirir ve genel awk ile çalışmaz ve özellikle yaygın olarak kullanılan mawk ile (örneğin Ubuntu'da varsayılan)
cipper

mawkUbuntu'da varsayılan olduğunu düşündüren nedir ? 15.04 VM'imde varsayılan awkdeğer gawk. Mawk kurulurken bu varsayılan değer değildir.
terdon

1
Eğer çağırırsanız bir awk betiği awk -f myscript.awk. Ancak, söz konusu sorunla ilgisi yoktur.
cipper

1
@EdMorton Bir awkbetik çünkü başlıyor #!/usr/bin/awk -f. Kabuk betikleri ile başlar #!/bin/sh(veya benzer bir şeyle).
Barmar

1
Çeşitli kabuk uzmanlarıyla konuştum ve bu bir kabuk veya awk betiği olup olmadığı konusunda kesin bir cevap almaya çalışıyorum ve şaşırtıcı bir şekilde POSIX'e göre # ile başlayan dosyaların yorumu! undefined ve belirli bir tür adı yok. Bazı insanlar buna bir kabuk veya awk komut dosyası yerine bir "karma patlama yorumlayıcı komut dosyası" derken, fikir birliği, çekirdek (kabuk değil) ilk satırı yorumlasa bile awk komut dosyası olarak düşünülmelidir. ilk satırı da (yorum olarak) ayrıştırabilmeli ve kullanarak çalıştırabilirsiniz awk -f file.
Ed Morton

Yanıtlar:


5

Cygwin bash GNU awk 4.1.3 ile:

$ cat tst.sh
#!/bin/awk -f
BEGIN { print "Executing:", ENVIRON["_"] }

$ ./tst.sh
Executing: ./tst.sh

Ne kadar portatif olduğunu bilmiyorum. Her zaman olduğu gibi, sadece olası işlevsellik sizi çalıyor gibi bir kabuk komut dosyası bir shebang kullanarak bir awk komut dosyası yürütmek olmaz. Basit tutun ve bunun yerine bunu yapın:

$ cat tst2.sh
awk -v cmd="$0" '
BEGIN { print "Executing:", cmd }
' "$@"

$ ./tst2.sh
Executing: ./tst2.sh

Sonuncusu, herhangi bir platformdaki herhangi bir kabuktaki herhangi bir modern awk ile çalışacaktır.


İlki sadece bash, zsh veya ksh olarak çalışır. Sonrası awk betiği değil, kabuk betiği ile ilgilidir.
cuonglm

2
Teşekkür ederim! ENVIRON["_"]mükemmel çalışıyor ve herhangi bir harici program çağırmıyor. İkinci seçenek awk -v ..., komut dosyasının nasıl çalıştırıldığına bağlıdır; Bunu istemiyorum.
cipper

1
Senaryonuzu aramak tst.shyanıltıcıdır. Bu bir awksenaryo, bir kabuk senaryosu değil. BEGINgeçerli bir kabuk komutu değil.
Barmar

1
Doğru ama taşınabilirlik sorusu "ENVIRON [] taşınabilir" değil " ENVIRON["_"]her kabuktan bir shebang aracılığıyla çağrılan her awk yazdırılırken çağıran kabuk komut dosyası yolu üretir mi? Ben şahsen cevap hakkında umurumda değil bir shebang bir awk komut dosyası aramak istiyorum ama sadece ben bahsettiğini düşündüm .... Oh yukarıdaki yorumlarda @cuonglm sadece bazı kabuklarda desteklendiğini yanıtladı .
Ed Morton

1
Güzel nokta, @Ed. Çizgide başarısız olarak doğrulandı (geçerli komutu yerine önceki komutu (veya kabuğun kendisini döndürür ). ksh93, yıldız işaretlerinde PID'yi ilginç bir şekilde önek olarak gösterir *12345*/tmp/test.awk. ARGV[0]her zaman awktire, bash, zsh ve ksh93 biçimindedir.
Adam Katz

5

Bunun gawk belgelere göre mümkün olduğunu düşünmüyorum :

Son olarak, değeri ARGV[0](bkz. Bölüm 7.5 Değişkenler) işletim sisteminize bağlı olarak değişir. Bazı sistemler awkoraya koyar , bazıları awk'ın tam yol adını (örneğin /bin/awk) ve bazıları da komut dosyanızın adını ('tavsiye') koyar. ARGV[0]Komut dosyası adınızı belirtmenin değerine güvenmeyin .

On linuxsizin kirli bir hack bir tür kullanmayı deneyin ve yorumlarına işaret olarak yapabilirsiniz Stéphane Chazelas uygulanması halinde bu mümkün awkdesteklerin NUL bayt:

#!/usr/bin/awk -f

BEGIN { getline t < "/proc/self/cmdline"; split(t, a, "\0"); print a[3]; }

komut dosyanız olduğu gibi çalışmıyor. Sadece "awk -f script.awk" ile çağrılırsa "k" yazdırır ve "./script.awk" ile çağrıldıysa "s" yazdırır
cipper

@cipper: Burada çalışır gawkve başarısız olur (açıklamanız gibi) mawk. İlginç!

Benim için Linux'ta çalışıyor, awk- 4.0.2. Freebsd ile /proc/curpoc/cmdlineve awksonuç seninki gibi ama ile çalışır gawk.
taliezin

Varsayılan olarak ubuntu çalışmaz. Taşınabilir bir çözüm bulmak güzel olurdu.
cipper

1
@taliezin: cuonglm'in cevabı bir çözüm değildir, çünkü betiği ismiyle manuel olarak beslemeyi gerektirir. Arama yapmak awk -vNAME="myscript.awk" ./myscript.awkve NAME komut dosyasının içine yazdırmak gibidir . Bir çözüm değil.
cipper

5

Komut adını awk içinden almanın doğrudan bir yolunu bilmiyorum. Ancak bunu bir alt kabuktan bulabilirsiniz.

gawk

GNU awk ve pskomut ile PROCINFO["PID"], komut adını geçici çözüm olarak almak için adresinden işlem kimliğini kullanabilirsiniz . Örneğin:

cmdname.awk

#!/usr/bin/gawk -f

BEGIN {
  ("ps -p " PROCINFO["pid"] " -o comm=") | getline CMDNAME
  print CMDNAME
}

mawk ve nawk

Aynı yaklaşım kullanır, ancak türetebilirsiniz awkgelen 'ın PID $PPID(PID ebeveynin) özel kabuk değişkeni:

cmdname.awk

#!/usr/bin/mawk -f

BEGIN { 
  ("ps -p $PPID -o comm=") | getline CMDNAME
  print CMDNAME
}

Test yapmak

Komut dosyasını şu şekilde çalıştırın:

./cmdname.awk

Her iki durumda da çıktı:

cmdname.awk

Bir hata aldım: / bin / sh: 1: -o: bulunamadı
cipper

@cipper: Bu sadece GNU awk ile çalışıyor, eksik shebang hattını ekledim.
Thor

Gönderen gawk kılavuzuna : POSIX'e göre, 'ifadesi | ifadesi '$' dışında sayılmamış işleçler içeriyorsa getline 'belirsizdir - örneğin, "" echo "" date "| getline 'belirsizdir, çünkü birleştirme operatörü parantez içinde değildir. '("Echo" "date") olarak yazmalısınız | getline 'programınızın tüm awk uygulamalarına taşınabilir olmasını istiyorsanız.
cipper

1
O ihtiyacı varsa gawko olduğunu gawkyerine çözüm awkçözümü. Bence @cipper, sorusuna "taşınabilir bir çözüm" dileğini eklemelidir.

1
@Thor: cuonglm tarafından cevap bir çözüm değildir, çünkü komut dosyasını adıyla manuel olarak beslemeyi gerektirir. Arama yapmak awk -vNAME="myscript.awk" ./myscript.awkve NAME komut dosyasının içine yazdırmak gibidir . Bir çözüm değil.
cipper

4

POSIX ile awk:

#!/usr/bin/awk -f

BEGIN {
    print ENVIRON["AWKSCRIPT"]
}

Sonra:

AWKSCRIPT=test.awk ./test.awk
test.awk

5
Komut dosyasının adını elle
beslersiniz

@cipper: Hayal edebileceğim en kolay ve taşınabilir yol bu.
cuonglm

3
Bu awk -vNAME="myscript.awk" ./myscript.awkdeğişkeni çağırmak ve sonra NAMEbetiğin içindeki değişkeni yazdırmak gibidir . Bir çözüm değil.
cipper

@cipper: Eğer bahsederseniz, bu tek yoldur mawk. Ayrıca kullanmak ENVIRON, kullanmakla aynı şey değildir -vNAME="myscript.awk", çünkü mawkkaçış sırasını ne zaman genişletecek NAME.
cuonglm

4

GNU awk kullanma

GNU awk kullanıcı kılavuzunu kontrol etme - 7.5.2 Aşağıdakilere rastladığım bilgileri ileten yerleşik değişkenler :

PROCINFO #

Bu dizinin öğeleri çalışan awk programı hakkındaki bilgilere erişim sağlar. Aşağıdaki öğelerin (alfabetik olarak listelenmiştir) kullanılabilir olması garanti edilir:

PROCINFO [ "PID" ']

Geçerli işlemin işlem kimliği.

Bu, çalışma zamanı sırasında programın PID'sini bildiğiniz anlamına gelir. Daha sonra, system()bu verilen PID ile süreci aramak için bir mesele kullanılır :

#!/usr/bin/gawk -f
BEGIN{ pid=PROCINFO["pid"]
       system("ps -ef | awk '$2==" pid " {print $NF}'")
}

Ben ps -ef, 2. sütunda PID görüntüleyen kullanın . Executiong üzerinden yapıldığını awk -f <script>ve başka parametreler olmadığını varsayarsak, satırın son alanının istediğimiz bilgileri içerdiğini varsayabiliriz.

Bazı parametrelerimiz olması durumunda, satırı farklı şekilde ayrıştırmamız gerekir -veya daha iyisi, pssadece ilgilendiğimiz sütunları yazdırmak için bazı seçeneklerden faydalanmamız gerekir.

Ölçek

$ awk -f a.awk 
a.awk
$ cp a.awk hello.awk
$ awk -f hello.awk 
hello.awk

Ayrıca GNU awk kullanım kılavuzunun başka bir bölümünün ARGV'nin gidilecek yol olmadığını söylediğini unutmayın:

1.1.4 Yürütülebilir awk Programları

Son olarak, ARGV [0] değeri (bkz. Yerleşik Değişkenler) işletim sisteminize bağlı olarak değişir. Bazı sistemler oraya 'awk', bazıları awk'ın tam yol adını (/ bin / awk gibi), bazıları ise betiğinizin adını ('tavsiye') koyar. (dc) Komut dosyası adınızı sağlamak için ARGV [0] değerine güvenmeyin.


ne yazık ki PROCINFO sadece bir gawk özelliği, genel awk değil. Örneğin (varsayılan olarak
ubuntu'da

Biliyorum ... Soruyu neden [gawk] ile etiketledin?
fedorqui

Haklısın. Soruyu gönderdiğimde mawk ve gawk arasındaki tüm bu farkların farkında değildim. Etiket şimdi mawk olarak değiştirildi.
cipper

@cipper good :) Aslında test yapıyordum mawkve çalıştıramadım, böylece Ubuntu'uma kurdum gawkve çalıştı. Yani bir geçici çözüm kullanmak olabilir gawk: D
fedorqui

1
@terdon, gawkUbuntu'ya (veya en azından mawkvarsayılan awkuygulamanın bulunduğu bazı Ubuntu sürümlerine) varsayılan olarak yüklenmez . IIRC, Debian'a da kurmak zorunda kaldım.
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.