Sürekli akış çıktısını manipüle etmek için sed nasıl kullanılır?


13

Teknik olmayan bir kitle için bir sunum hazırlıyorum. Birkaç önemli olan sürekli bir değer akışı çıktı bash içinde çalışan bir program var. İzleyicilerin sıklıkları hakkında bir fikir edinebilmeleri için önemli sonuçları gösterildikçe vurgulamak istiyorum. Sorun şu ki sed, çalışan bir akışta işlem yapamıyorum . Sonuçları bir dosyaya koyarsam iyi çalışır:

cat output.txt | sed "s/some text/some text bolded/"

Ama aynı şeyi çalışan çıktı üzerinde denerseniz, şöyle:

command | sed "s/some text/some text bolded/"

sedhiç birşey yapmıyor. Düşüncesi olan var mı?

Lambert, işaret edecek kadar yardımcı olduğu için sed, hiçbir şey yapmadığını söylemem belirsizdi. Olan şey, programın , pipetlenmiş olsa bile, normalde olduğu gibi stdout(yazmadığından eminim stderr) çıktısıdır sed.

Sorun, komutun daha sonra stdout'a çıktı veren ikinci bir program çağırması gibi görünüyor. İlk program tarafından basılan birkaç satır vardır; bunları düzenleyebilirim. Sonra ikinci program tarafından basılan bir değer akışı vardır; bunları düzenleyemiyorum.

Perl ve awk yöntemleri de çalışmaz.


5
Mu stdbuf -o0 command | sed "s/some text/some text bolded/"iş?
FloHimself

3
'Sed ile hiçbir şey yapmazsınız' ile oyuncu değişikliği yapılmaz mı, yoksa çıktılarınız olmaz mı? Komut stdout yerine stderr'e yazıyor olabilir mi? Kullanabileceğiniz bir şeyi vurgulamak istiyorsanızcommand|egrep 'some text|$'
Lambert

Komut stdout'a yazılıyor mu (stderr'a değil)?
Anthon

1
Metnin bir kereden fazla göründüğü göz önüne alındığında, bir g"global" ikame eklemeniz gerekir , aksi takdirde bir satırdaki yalnızca ilk kez yer değiştirilir:sed "s/old/new/g"
ph0t0nix

@ ph0t0nix Hayır, sorun bu değil, ancak bu bir sorun olurdu. Bahşiş için teşekkürler.
P Jones

Yanıtlar:


12

Büyük olasılıkla komutun çıktısının arabelleğe alınmasıdır. Komut bir terminale yazdığında, her satırda arabellek temizlenir, böylece beklenen hızda göründüğünü görürsünüz. Komut bir boruya yazdığında, arabellek yalnızca birkaç kilobayta ulaştığında temizlenir, bu nedenle çok fazla gecikir. Standart giriş / çıkış kütüphanesinin varsayılan davranışı budur.

Komutu çıktısını açıklamamaya zorlamak için unbuffer(beklemeden) veya stdbuf(GNU coreutils'ten) kullanabilirsiniz.

unbuffer command | sed …
stdbuf -o0 command | sed …

stdbufişe yaramadı (daha önce bahsedilen, btw), ama unbufferyaptım! Beni ne kadar mutlu ettiğine dair hiçbir fikrin yok.
P Jones

Kısa açıklama için teşekkürler. Çok yararlı.
P Jones

sedkendisi böyle bir tampon kullanır (cf ChennyStar post), bu yüzden buradaki örnekler tampondan sedçıkartılacağı commandiçin işe yaramayabilir : cat /etc/passwd | unbuffer sedancak sedkendisinin bir -useçeneği vardır, bu nedenle grepbu örneklerde daha uygun olabilir. Arka plan bilgileriniz için çok teşekkürler! Mükemmel cevap!
matematik

4

sed bunun için bir seçenek var:

-u, - karıştırılmamış

Girdi dosyalarından minimum miktarda veri yükler ve çıktı arabelleklerini daha sık temizler. Daha man sedfazla bilgi için bakınız.


1
sedSadece GNU (BSD değil sed) ve bunun hala boru başlangıcında komutun arabelleğe alınmasını engellemeyeceğine inanıyorum. Ama bundan bahsetmek güzel. :)
Joker

stdbuf manpage "COMMAND standart akışlarının arabelleğe alınmasını ayarlarsa (örneğin" tee "yaparsa)," stdbuf "ile ilgili değişiklikleri geçersiz kılacağını belirtir. Sed bu kategoriye girebilir, ancak '-u' bayrağı tamponlanmamış bir boru zincirinde faydalı olacaktır.
MattSmith

2

Awk kullanırdım

  command | awk '/some important stuff/ { printf "%c[31m%s%c[0m\n",27,$0,27 ; next }
  { print ; } '

nerede

  • /some important stuff/ sed gibi önemli bir satır seçin
  • printf "%c[31m%s%c[0m\n",27,$0,27 ; kırmızı baskı
    • yeşil, sarı için 32,33 kullanın ...
    • 1 $, 2 $, belirli bir alanı seçmek için kullanılabilir
  • diğer satırlar sadece 'olduğu gibi' yazdırılır

kilit nokta, commandçizgileri yıkamasıdır, ancak çok fazla çıktınız varsa durum böyle olmalıdır.


Not: Soru, tüm satırın "kalın" olması gerektiğini değil, yalnızca "bir miktar metin" olması gerektiğini söylüyor. Bu özelliği awk( sub()veya kullanarak gsub()) da uygulamak mümkün olsa da , bu ilkel ikame seddurumunda kesinlikle uygun bir araçtır.
Janis

1

Perl yolu:

command | perl -pe 's/(stuff)/\x1b[1m$1\x1b[0m/g'

veya sürekli çıktı ile:

Çıktı için bir bash betiği cont:

#!/bin/bash
while [ true ]
do
   echo "Some stuff"
done

Şununla test et:

./cont | perl -pe 's/(stuff)/\x1b[1m${1}\x1b[0m/g'
  • \x1b[1m - kalın veya artan yoğunluk
  • ${1} - backreferenze
  • \x1b[0m - tüm özellikleri sıfırla

Çıktı:

Bazı şeyler
Bazı şeyler
Bazı şeyler
Bazı şeyler

Burada daha fazla kaçış kodu var .

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.