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