GNU/Linux >> Znalost Linux >  >> Linux

Příkaz pro výstup každého řádku dopředu a poté zpět

Funkce shellu. Toto bude fungovat v jakémkoli prostředí, které podporuje <<< zde-řetězce, včetně zsh a bash.

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

Ve většině případů bude mnoho problémů kvůli způsobu, jakým funguje stdio vyrovnávací paměť. Řešením pro linux může být použití stdbuf naprogramujte a spusťte příkaz s coproc, takže můžete explicitně ovládat prokládání výstupu.

Následující předpokládá, že příkaz vypíše jeden řádek po každém řádku vstupu.

#!/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

Pokud je potřeba obecnější řešení, protože OP vyžaduje pouze to, aby každý řádek vstupu do programu nakonec vypíše jeden řádek spíše než okamžitě, pak je zapotřebí složitější přístup. Vytvořte smyčku událostí pomocí read -t 0 zkuste číst ze stdin a co-process, pokud máte stejné "číslo řádku" pro oba, pak výstup, jinak uložte řádek. Abyste se vyhnuli použití 100 % procesoru, pokud v kterémkoli kole smyčky událostí ani jeden nebyl připraven, zaveďte malé zpoždění před dalším spuštěním smyčky událostí. Pokud proces vydává částečné řádky, dochází k dalším komplikacím, které je třeba uložit do vyrovnávací paměti.

Pokud je potřeba toto obecnější řešení, napsal bych to pomocí očekávání, protože již má dobrou podporu pro zpracování porovnávání vzorů na více vstupních tocích. Toto však není řešení bash/zsh.


V tomto konkrétním případě bych použil perl :

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

Což byste mohli rozšířit také na práci se shluky grafémů:

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

Nebo zsh :

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

I když bych se vyhnul použití while read smyčky pro zpracování textu, dokonce i v zsh (i když v tomto konkrétním případě to není tak špatné, protože se používají pouze vestavěné příkazy).

V obecném případě je použití dočasných souborů pravděpodobně nejlepším přístupem. S zsh , můžete to udělat pomocí:

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

(kde =(...) se stará o vytvoření a vyčištění dočasného souboru).

Nahraďte to rourami a nějakou formou tee ing je recept na uváznutí v obecném případě. Některé přístupy a podrobnosti o situacích uváznutí naleznete v těchto podobných otázkách:

  • Rozdělte vstup pro různé příkazy a zkombinujte výsledek
  • tee + cat:použijte výstup několikrát a poté zřetěďte výsledky

Linux
  1. Získejte první řádek výstupu příkazu shellu

  2. Předpona každého výstupu příkazu za běhu

  3. Příkazový řádek:Extrahujte podřetězec z výstupu

  1. Jak zjistit, jakou verzi OS X používám z příkazového řádku?

  2. Zpracovat každý řádek výstupu z `ping` okamžitě v potrubí?

  3. Jak analyzovat každý řádek textového souboru jako argument příkazu?

  1. Sloučit soubory VOB pomocí příkazového řádku?

  2. Iterování přes každý řádek výstupu ls -l

  3. Připojte konec řádku k výstupu příkazu