GNU/Linux >> Belajar Linux >  >> Linux

Perintah untuk menampilkan setiap baris maju lalu mundur

Fungsi cangkang. Ini akan berfungsi di semua shell yang mendukung <<< di sini-string, termasuk zsh dan bash.

xyz() { 
    while read line
    do 
        printf "%s " "$line"
        "[email protected]" <<<"$line"
    done
}
$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab

Akan ada banyak masalah dalam banyak kasus karena cara kerja stdio buffering. Solusi untuk linux mungkin menggunakan stdbuf program dan jalankan perintah dengan coproc, sehingga Anda dapat secara eksplisit mengontrol interleaving keluaran.

Berikut ini mengasumsikan bahwa perintah akan menampilkan satu baris setelah setiap baris masukan.

#!/bin/bash
coproc stdbuf -i0 -o0 "[email protected]"
IFS=
while read -r in ; do
    printf "%s " "$in"
    printf "%s\n" "$in" >&${COPROC[1]}
    read -r out <&${COPROC[0]}
    printf "%s\n" "$out"
done

Jika diperlukan solusi yang lebih umum karena OP hanya memerlukan setiap baris masukan ke program untuk pada akhirnya output satu baris daripada segera, maka diperlukan pendekatan yang lebih rumit. Buat loop peristiwa menggunakan read -t 0 untuk mencoba dan membaca dari stdin dan proses bersama, jika Anda memiliki "nomor baris" yang sama untuk keduanya, maka hasilkan, jika tidak, simpan baris tersebut. Untuk menghindari penggunaan 100% cpu jika di putaran mana pun loop acara tidak ada yang siap, maka perkenalkan penundaan kecil sebelum menjalankan loop acara lagi. Ada komplikasi tambahan jika proses mengeluarkan sebagian baris, ini perlu di-buffer.

Jika solusi yang lebih umum ini diperlukan, saya akan menulis ini menggunakan ekspektasi karena sudah memiliki dukungan yang baik untuk menangani pencocokan pola pada beberapa input stream. Namun ini bukan solusi bash/zsh.


Dalam kasus khusus ini, saya akan menggunakan perl :

printf '%s\n' foo bar | perl -Mopen=locale -lpe '$_ .= " " . reverse$_'
foo oof
bar rab

Yang dapat Anda kembangkan untuk juga berfungsi dengan kluster grafem:

$ printf '%s\n' $'complique\u301' |
    perl -Mopen=locale -lpe '$_ .= " " . join "", reverse/\X/g'
compliqué éuqilpmoc

Atau zsh :

while IFS= read -r line; do
  print -r -- $line ${(j::)${(s::Oa)line}}
done

Meskipun saya akan menghindari penggunaan while read loop untuk memproses teks, bahkan di zsh (meskipun dalam kasus khusus ini, tidak terlalu buruk karena hanya perintah bawaan yang digunakan).

Dalam kasus umum, menggunakan file temp mungkin merupakan pendekatan terbaik. Dengan zsh , Anda dapat melakukannya dengan:

(){paste -d ' ' $1 <(rev <$1)} =(print -l foo bar)

(di mana =(...) menangani pembuatan dan pembersihan file temp).

Menggantinya dengan pipa dan beberapa bentuk tee ing adalah resep untuk kebuntuan dalam kasus umum. Lihat pertanyaan serupa ini untuk beberapa pendekatan dan detail tentang situasi kebuntuan:

  • Pisahkan input untuk perintah yang berbeda dan gabungkan hasilnya
  • tee + cat:gunakan keluaran beberapa kali lalu gabungkan hasil

Linux
  1. Bagaimana Mengenalinya Versi Os X Saya Dari Baris Perintah?

  2. Proses Setiap Baris Output Dari `ping` Segera Di Pipeline?

  3. Utilitas Baris Perintah Untuk Mengambil Kata Sandi, Yang Tidak Memiliki Gema Kembali?

  1. Bash Script:Bagaimana Menetapkan Setiap Baris Perintah Output Ke Nilai Dalam Array?

  2. Gabungkan File Vob Melalui Baris Perintah?

  3. Dapatkan baris pertama dari keluaran perintah shell

  1. Bagaimana Mengurai Setiap Baris File Teks Sebagai Argumen Untuk Perintah?

  2. Mengulangi setiap baris keluaran ls -l

  3. Bash jika dalam satu baris