Hogyan elemezzük a szövegfájl minden sorát argumentumként egy parancsnak?

Olyan szkriptet szeretnék írni, amely .txt fájlnevet vesz fel argumentumként, felolvassa a fájl sort soronként, és minden sort átad egy parancsnak. Például futtatja command --option "LINE 1", majd command --option "LINE 2" stb. egy másik fájlba van írva. Hogyan tudom ezt csinálni? Nem tudom, hol kezdjem.

Válasz

Használja a while read ciklust:

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

A másik a kimenet blokkonkénti átirányítása:

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

Utolsó a fájl megnyitása:

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 

Ha az egyik parancs bemenetet olvas, akkor jó lenne ötlet, hogy egy másik fd-t használjon bemenetként, így a parancsok nem fogják megenni (itt feltételezve a ksh, zsh vagy bash a -u 3 esetén a <&3 helyett használja hordozhatóan):

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

Fin szövetségese az érvek elfogadásához:

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

Melyik futtatható:

bash script.sh file another_file 

Extra ötlet. A bash használatával használja az readarray:

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

Megjegyzés: IFS= elhagyható, ha nem törődik azzal, hogy a sorértékeket levágja a vezető és a záró szóköz.

Válasz

Egy másik lehetőség: xargs.

GNU-val xargs:

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

{} a szövegsor helytartója.

Egyéb xargs általában nincs -a, -d, de van, akinek -0 NUL-elválasztott bemenethez. Ezekkel a következőket teheti:

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

Unix-megfelelő rendszereken (a -I opcionális a POSIX rendszerben, és csak szükséges UNIX-megfelelő rendszerekhez), akkor elő kell dolgoznia a bemenetet, hogy idézze a sorokat a xargs elvárt formátumban:

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

Ne feledje azonban, hogy egyes xargs megvalósítások nagyon alacsony határt szabnak az argumentum maximális méretének (például a Solarison 255, a Unix specifikáció által megengedett minimum).

Megjegyzések

  • kicsinyíthető <file xargs -L 1 -I{} command --option {} other args
  • @iruvar, nem, ez feldolgozná az idézeteket és eltávolítana néhány üres helyet.

Válasz

Pontosan megtartva a kérdésre:

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

Megjegyzések

  • varázslatosan működtek 🙂
  • +1 szerette ezt, köszönöm

Válasz

A legjobb válasz und is:

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

SZERKESZTÉS:

… négy évvel később …

több leszavazás és további tapasztalat után most a következőket ajánlanám:

xargs -l COMMAND < file 

Megjegyzések

  • Ez egyszer meghívja a parancsot a fájl minden szava számára. Ezenkívül mindig idézzen hivatkozásokat a shell változókra (például a do "$cmd" "$i"; dokumentumban), hacsak nincs oka arra, hogy ne; ha a fájl magában tartalmazna egy * szót, akkor a kód futtatná a $cmd * parancsot, amely természetesen a az aktuális könyvtárban található fájlok listája.
  • @ G-Man, a zsh kivételével, a `cat` már kibővítené a * -et (a nem idézett $i akkor is kibővíthetne néhány helyettesítő karaktert (egy második kör), ha a bemutat néhányat). Mindenesetre ez a megközelítés valóban téves.
  • +1. Ez jól fog működni, ha minden sor csak azt a bemenetet tartalmazza, amely a szóköz nélküli parancshoz szükséges.
  • +1, tetszett xargs megoldás
  • Ez működik! (a későbbi szerkesztés xargs -l COMMAND < file). Köszönöm!

Válasz

 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 

KIMENET

--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 

Válasz

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

Vegye el az összes Egy fájl sorait, és argumentumként adja át egyetlen parancsnak, azaz:

command line1 line2 line3 .... 

Ha a --option minden sort megelőző jelző megváltoztatja a második parancsot:

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

Megjegyzések

  • Mire -1 az ed használatával … valóban?
  • Nem ‘ nem mondtam le téged, de annak a személynek valószínűleg ezek voltak az okai: (1) Ez nem így van mit kér a kérdés. Ez egyszer meghívja a parancsot, a fájl összes tartalmával a parancssorban; nem pedig soronként egyszer .(2) Ez nem segít a héjra jellemző karakterek kezelésében (amelyek a fájlban lehetnek); pl. ', ", <, >, ; stb. (3) Ez felesleges ideiglenes fájlt hoz létre. (4) Az ilyen dolgokat általában az „itt dokumentumokkal” végzik. (5) Az ed parancsai esetlenek; az első két parancs csökkenthető %s/^/ / és %j.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük