Boru bash dizisi manipülasyonu


9

Diğer bazı boru bash dize manipülasyon soruları okudum ama onlar özel uygulamalar gibi görünüyor.

Esasen, aşağıdakileri daha basit yapmanın bir yolu var mı?

onun yerine

$ string='hello world'; string2="${string// /_}"; echo "${string2^^}"
HELLO_WORLD

gibi bir şey

$ echo 'hello world' | $"{-// /_}" | "${ -^^}"
HELLO_WORLD

Hızı korumak için mümkünse bash manipülasyonları içinde kalmakla ilgileniyorum (scriptlerimi büyük ölçüde yavaşlatma eğilimi olan sed / awk'ın aksine)

Edit2: @jimmij

İkinci örneği beğendim ve bir işlev yapmaya yöneldim.

bash_m() { { read x; echo "${x// /_}"; } | { read x; echo "${x^^}"; }; }
echo hello world | bash_m
HELLO_WORLD

1
sence sed / awk bu amaç için neden yavaş olsun? Geldikleri kadar hızlıdırlar.
mkc

1
@Ketan Sed ve awk ayrı süreçlerdir, bu yüzden bash'ın ayrı bir işlem başlatmadan yerel olarak yapabileceği bir şey olarak asla hızlı olamazlar. Normalde bu fark neredeyse hiç fark edilmez, ancak kabuk komut dosyalarındaki performansın genellikle belirli bir döngü veya hesaplama çok fazla kez tekrarlandığı ve binlerce işlemin doğuşunda basit bir dize manipülasyonu yapmaktan belirgin şekilde daha yavaş olacaktır.
jw013

2
@ jw013 Bu, kısa dizeler için sorudan "merhaba dünya" olarak geçerlidir, ancak dize çok uzunsa, trel kitabını söyleyin , o zaman tersi doğrudur, çünkü işlemlerin ortaya çıkma süresi, dize manipülasyon zamanına kıyasla ihmal edilebilir. sedve awkadanmıştır. Dize çok uzunsa, tüm bash kılavuzunu söyle, o zaman bash bazı iç sınırlamalar nedeniyle tamamen ilerlemeyi reddedebilir.
jimmij

2
@ jw013 O bash dize manipülasyon kodunu iddia ediyorum gibi daha az verimli sonra adanmış araçları sed, awk, trveya benzeri. Bir süre önce tam olarak bu bilgileri ekleyerek değiştirdiğim gena2x cevabına bakın: unix.stackexchange.com/questions/162221/… terdon cevabı ile kısa dizeler için zaman verdiği aynı soruya karşılaştırmak isteyebilirsiniz. vaka süreci yumurtlama çoğu zaman alır. Kendiniz test edebilir ve sonuç gönderebilirsiniz.
jimmij

1
@Miati Neden bu ekstraın read x; echo $xperformans için daha iyi olduğunu düşünüyorsunuz ? Sözdizimi daha kısa veya daha temiz görünmüyor. x=${x// /_}; x=${x^^}aynı şeyi yapmanın çok daha özlü bir yoludur {read x; echo ${x.... Performansa gelince, @jimmij çatal sayısının eşit olduğunu tr/ seddaha hızlı olacağını belirtti bash. Bir boru kullanmak her zaman ekstra bir işlemle sonuçlanır, böylece çatal kaydetme argümanı artık geçerli değildir. Bu nedenle, eğer boru kullanıyorsanız, sadece sed/ trvb read x; echo $x.
jw013

Yanıtlar:


9

Jimmij ne dedi. Onun son örneği, borulu ifadenizde denediğiniz şeye en yakın olanıdır.

İşte bu temanın bir çeşidi:

echo 'hello world'|echo $(read s;s=${s^^};echo ${s// /_})

Kullanmaya meyilliyim tr, çünkü oldukça hızlı.

echo 'hello world'|tr ' [:lower:]' '_[:upper:]'

Sanırım bash iç içe parametre genişlemesine izin vermiyor bir utanç; OTOH, bu tür iç içe ifadelerin kullanımı kolayca okunması kolay bir koda yol açabilir. Mümkün olduğunca hızlı çalışacak şeylere gerçekten ihtiyacınız olmadığı sürece , hata ayıklamak için bir PITA olan akıllı görünümlü kod yerine, okunması, anlaşılması ve bakımı kolay kod yazmak daha iyidir. Eğer gerçekten eğer yapmak gerek şeyleri derlenmiş kodu kullanarak gereken sürat yapılması gereken değil bir senaryo.


7

Parametre genişletmelerini bu şekilde geçiremezsiniz. Sembolü formda olarak xkullanmaya atıfta bulunursanız, en azından standart bir giriş değil, gerçek değişken adı olmalıdır . In size şu şekilde iç içe parametre değiştirmelerin gerçekleştirebilir:$"${x}"bashzsh

$ x=''hello world'
$ echo ${${x// /_}:u}
HELLO_WORLD

(Not: :uiçin zshaynı ^^için bash)

Bash içinde yuvalamak mümkün değildir ve söz konusu yazdığınız şeyin en iyisi olduğunu düşünüyorum, ancak garip bir nedenden dolayı boruları denkleme dahil etmeniz gerekiyorsa, bunu denemek isteyebilirsiniz:

$ echo 'hello world' | { read x; echo "${x// /_}"; } | { read y; echo "${y^^}"; }
HELLO_WORLD

1
Nasıl hakkında kısa süre önce konuşma düşünüldüğünde tr/ seddaha hızlı olan bashdize işlemcilikte ve standart I / O ile dizeleri geçmek boruları nasıl kullandıklarını düşünüyor, ben aksine bash bu işlemleri yapmaya tam anlamıyla sıfır noktaya bakın tr/ ' sed. Neden hiç kimse | { read x; echo $x... }bunun yerine | sedaynı şeyi yapar?
jw013

1
@ jw013 açıkçası ben hiçbir anlamı yanında görüyorum. Bu sadece boruları soruna zorla dahil etmek için bir örnektir, çünkü OP açıkça istediler ve harici programları kullanmak istemedi (hem echove readbash yerleşiktir, bu yüzden prensip olarak biraz daha hızlıdır). Zaten cevap yazarken OP hangi soru ilerici parametre manipülasyonları bash bu görev için bence alabilirsiniz en iyisidir. Her neyse, sorun oldukça akademik.
jimmij
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.