Hvordan analyserer jeg hver linje i en tekstfil som et argument til en kommando?

Jeg ønsker at skrive et script, der tager et .txt filnavn som argument, læser fillinjen efter linje og sender hver linje til en kommando. For eksempel kører den command --option "LINE 1", derefter command --option "LINE 2" osv. Udgangen af kommandoen er skrevet til en anden fil. Hvordan skal jeg gøre det? Jeg ved ikke, hvor jeg skal starte.

Svar

Brug while read loop:

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

En anden er at omdirigere output ved blok:

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

Sidste er at åbne filen:

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 

Hvis en af kommandoerne læser input, ville det være en god idé om at bruge en anden fd til input, så kommandoerne ikke spiser det (her forudsat ksh, zsh eller bash til -u 3, brug <&3 i stedet bærbart):

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

Fin allieret for at acceptere argumenter, kan du gøre:

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

Hvilken man kan køre som:

bash script.sh file another_file 

Ekstra idé. Brug bash, brug readarray:

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

Bemærk: IFS= kan udelades, hvis du ikke har noget imod at have linjeværdier trimmet af mellemrum i forkant og bagud.

Svar

En anden mulighed er xargs.

Med GNU xargs:

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

{} er pladsholderen for tekstlinjen.

Andet xargs har generelt ikke -a, -d, men nogle har -0 til NUL-afgrænset input. Med disse kan du gøre:

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

På Unix-kompatible systemer (-I er valgfri i POSIX og kun krævet til UNIX-kompatible systemer), skal du forbehandle input til citat linjerne i det format, der forventes af xargs:

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

Bemærk dog, at nogle xargs implementeringer har en meget lav grænse for argumentets maksimale størrelse (f.eks. 255 på Solaris, det minimum, der er tilladt i Unix-specifikationen).

Kommentarer

  • reducerbar til <file xargs -L 1 -I{} command --option {} other args
  • @iruvar, nej, det ville behandle citater og fjerne nogle blanke.

Svar

Holder nøjagtigt til spørgsmålet:

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

Kommentarer

  • fungerede som charme 🙂
  • +1 elskede dette tak

Svar

Det bedste svar jeg har und er:

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

EDIT:

… fire år senere …

efter flere nedstemninger og lidt mere erfaring, vil jeg anbefale følgende nu:

xargs -l COMMAND < file 

Kommentarer

  • Dette påkalder kommandoen en gang for hvert ord i filen. Du bør også altid citere henvisninger til shellvariabler (som i do "$cmd" "$i";), medmindre du har en grund til ikke at; hvis filen indeholdt en * som et ord i sig selv, ville din kode køre $cmd *, hvilket naturligvis ville køre kommandoen med en liste over filerne i den aktuelle mappe.
  • @ G-Man, undtagen i zsh, `cat` ville allerede udvide * (den ikke-citerede $i kunne stadig udvide noget jokertegn (en anden runde), hvis udvidelsen af `cat` introducerer nogle). Under alle omstændigheder er denne tilgang faktisk forkert.
  • +1. Dette fungerer fint, hvis hver linje kun indeholder det input, der er nødvendigt for kommandoen, der bruges uden mellemrum.
  • +1, kunne lide xargs-løsning
  • Dette fungerer! (den senere redigering xargs -l COMMAND < file). Tak!

Svar

 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 

OUTPUT

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

Svar

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

Tag alle de linjer i en fil og videresende dem som argumenter til en enkelt kommando, dvs.

command line1 line2 line3 .... 

Hvis du har brug for --option flag forud for hver linje, skift den anden kommando til:

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

Kommentarer

  • Hvad -1 for bruger ed … virkelig?
  • Jeg ' t nedstemte dig, men den person, der sandsynligvis havde følgende grunde: (1) Dette gør det ikke hvad spørgsmålet beder om. Dette påkalder kommandoen en gang med alt indholdet af filen på kommandolinjen; snarere end en gang pr. linje .(2) Dette håndterer intet for at håndtere tegn, der er specielle for skallen (der kan være i filen); f.eks. ', ", <, >, ; osv. (3) Dette skaber en unødvendig midlertidig fil. (4) Ting som dette gøres generelt med “her dokumenter”. (5) Dine ed kommandoer er klodset; de to første kommandoer kan reduceres til %s/^/ / og %j.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *