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

Chci napsat skript, který jako argument použije název .txt, přečte řádek souboru podle řádku a předá každý řádek příkazu. Například spustí příkaz command --option "LINE 1", poté command --option "LINE 2" atd. Výstup příkazu je zapsán do jiného souboru. Jak to mám udělat? Nevím, kde začít.

Odpovědět

Použijte while read smyčku:

: > another_file ## Truncate file. while IFS= read -r LINE; do command --option "$LINE" >> another_file done < file 

Další možností je přesměrovat výstup pomocí bloku:

while IFS= read -r LINE; do command --option "$LINE" done < file > another_file 

Poslední je otevření souboru:

exec 4> another_file while IFS= read -r LINE; do command --option "$LINE" >&4 echo xyz ## Another optional command that sends output to stdout. done < file 

Pokud jeden z příkazů přečte vstup, bylo by dobré nápad použít pro vstup další fd, takže příkazy to nebudou jíst (zde za předpokladu ksh, zsh nebo bash pro -u 3 použijte <&3 místo toho přenosně):

while IFS= read -ru 3 LINE; do ... done 3< file 

Fin spojenec pro přijetí argumentů, můžete udělat:

#!/bin/bash FILE=$1 ANOTHER_FILE=$2 exec 4> "$ANOTHER_FILE" while IFS= read -ru 3 LINE; do command --option "$LINE" >&4 done 3< "$FILE" 

Který z nich může běžet jako:

bash script.sh file another_file 

Extra nápad. V bash použijte readarray:

readarray -t LINES < "$FILE" for LINE in "${LINES[@]}"; do ... done 

Poznámka: IFS= lze vynechat, pokud vám nevadí, že řádkové hodnoty budou oříznuty na začátku a na konci mezer.

Odpovědět

Další možností je xargs.

S GNU xargs:

xargs -a file -I{} -d"\n" command --option {} other args 

{} je zástupný znak pro řádek textu.

Další xargs obecně nemají -a, -d, ale některé mají -0 pro vstup oddělený NUL. S nimi můžete:

< file tr "\n" "\0" | xargs -0 -I{} command --option {} other args 

V systémech vyhovujících Unixu (-I je v POSIXu volitelný a pouze vyžadováno pro systémy vyhovující systému UNIX), je třeba předem zpracovat vstup pro citaci řádků ve formátu očekávaném xargs:

< file sed "s/"/"\\""/g;s/.*/"&"/" | xargs -E "" -I{} command --option {} other args 

Mějte však na paměti, že některé implementace xargs mají velmi nízkou hranici maximální velikosti argumentu (například 255 v systému Solaris, minimum povolené specifikací Unixu.

Komentáře

  • redukovatelné na <file xargs -L 1 -I{} command --option {} other args
  • @iruvar, ne, to by zpracovalo nabídky a odstranilo nějaké mezery.

Odpověď

Přesné dodržování na otázku:

#!/bin/bash # xargs -n param sets how many lines from the input to send to the command # Call command once per line [[ -f $1 ]] && cat $1 | xargs -n1 command --option # Call command with 2 lines as args, such as an openvpn password file # [[ -f $1 ]] && cat $1 | xargs -n2 command --option # Call command with all lines as args # [[ -f $1 ]] && cat $1 | xargs command --option 

Komentáře

  • fungovaly jako kouzlo 🙂
  • +1 se to líbilo, díky

odpověď

nejlepší odpověď und je:

for i in `cat`; do "$cmd" "$i"; done < $file 

EDIT:

… o čtyři roky později …

po několika hlasováních dolů a dalších zkušenostech bych teď doporučil následující:

xargs -l COMMAND < file 

Komentáře

  • Tím se příkaz vyvolá jednou pro každé word v souboru. Měli byste také vždy citovat odkazy na proměnné prostředí (jako v do "$cmd" "$i";), pokud pro to nemáte důvod; pokud soubor obsahoval * jako slovo samo o sobě, váš kód by spustil $cmd *, což by samozřejmě spustilo příkaz s seznam souborů v aktuálním adresáři.
  • @ G-Man, kromě zsh, `cat` by již rozšířil * (nekótovaný $i by mohl ještě rozšířit nějaký zástupný znak (druhé kolo), pokud by rozšíření `cat` zavádí některé). V každém případě je tento přístup skutečně špatný.
  • +1. To bude fungovat dobře, pokud každý řádek obsahuje pouze vstup potřebný pro použitý příkaz bez mezer.
  • +1, oblíbené řešení xargs
  • to funguje! (pozdější úprava xargs -l COMMAND < file). Děkujeme!

Odpověď

 sed "s/"/"\\\\""/g;s/.*/\$* "&"/" <<\FILE |\ sh -s -- command echo --option all of the{&}se li$n\es "are safely shell quoted and handed to command as its last argument following --option, and, here, before that echo FILE 

VÝSTUP

--option all of the{&}se li$n\es "are safely shell --option quoted and handed to command as its last argument --option following --option, and, here, before that echo 

Odpověď

ed file.txt %g/^/s// / 2,$g/^/-,.j 1s/^/command/ wq chmod 755 file.txt ./file.txt 

Vezměte všechny řádky souboru a předat je jako argumenty jedinému příkazu, tj.

command line1 line2 line3 .... 

Pokud potřebujete --option příznak před každým řádkem změňte druhý příkaz na:

%g/^/s// --option / 

Komentáře

  • Co -1 pro používám ed … opravdu?
  • Nechtěl jsem tě ' přehlasovat, ale ten, kdo to udělal, měl pravděpodobně tyto důvody: (1) To nedělá na co se otázka ptá. Toto vyvolá příkaz jednou se všemi obsahy souboru na příkazovém řádku; spíše než jednou na řádek .(2) Nedělá to nic pro zpracování znaků, které jsou speciální pro shell (který může být v souboru); např. ', ", <, >, ; atd. (3) Tím se vytvoří nepotřebný dočasný soubor. (4) Věci jako toto se obvykle dějí s „zde dokumenty“. (5) Vaše ed příkazy jsou neohrabané; první dva příkazy lze snížit na %s/^/ / a %j.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *