Kuinka jäsentää tekstitiedoston kukin rivi argumenttina komennolle?

Haluan kirjoittaa komentosarjan, joka käyttää argumenttina .txt -tiedostonimeä, lukee tiedostorivin rivillä ja välittää kukin rivi komennolle. Esimerkiksi se suorittaa command --option "LINE 1", sitten command --option "LINE 2" jne. Komennon lähtö on kirjoitettu toiseen tiedostoon. Kuinka teen sen? En tiedä mistä aloittaa.

Vastaa

Käytä while read -silmukkaa:

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

Toinen on ohjata ulostulo lohkolla:

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

Viimeinen on tiedoston avaaminen:

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 

Jos joku komennoista lukee syötettä, se olisi hyvä idea käyttää toista fd: tä syötteenä, jotta komennot eivät syö sitä (tässä olettaen ksh, zsh tai bash kohteelle -u 3, käytä sen sijaan kannettavasti <&3:

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

Fin liittolainen hyväksymään argumentit, voit tehdä seuraavaa:

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

Kumpi voisi toimia nimellä:

bash script.sh file another_file 

Ylimääräinen idea. Käytä bash -kohdassa readarray:

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

Huomaa: IFS= voidaan jättää pois, jos et halua, että viiva-arvot on leikattu etu- ja lopputiloista.

Vastaa

Toinen vaihtoehto on xargs.

GNU: lla xargs:

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

{} on tekstirivin paikanpitäjä.

Muu xargs ei yleensä ole -a, -d, mutta joillakin on -0 NUL-erotetulle tulolle. Niillä voit tehdä seuraavaa:

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

Unix-yhteensopivissa järjestelmissä (-I on valinnainen POSIX-järjestelmässä ja vain vaaditaan UNIX-yhteensopiville järjestelmille), sinun on esikäsiteltävä syöte lainaamaan rivit xargs:

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

Huomaa kuitenkin, että joillakin xargs -toteutuksilla on hyvin pieni argumentin enimmäiskoko (esimerkiksi Solariksessa 255, Unix-määrityksen sallima vähimmäismäärä).

Kommentit

  • pelkistettävä muotoon <file xargs -L 1 -I{} command --option {} other args
  • @iruvar, ei, se käsittelisi lainausmerkkejä ja poistaisi joitain aihioita.

Vastaa

Pitää tarkasti kysymykseen:

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

kommentit

  • toimi kuin viehätys 🙂
  • +1 rakasti tätä, kiitos

Vastaa

Paras vastaus und is:

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

MUOKKAA:

… neljä vuotta myöhemmin …

useiden alas-äänestysten ja jonkin verran kokemuksen jälkeen suosittelisin seuraavaa nyt:

xargs -l COMMAND < file 

Kommentit

  • Tämä kutsuu komennon kerran jokaiselle tiedoston sanalle . Sinun tulee myös lainata viittauksia kuorimuuttujiin (kuten kohdassa do "$cmd" "$i";), ellei sinulla ole syytä olla; jos tiedosto sisältäisi itsessään sanana *, koodisi toimisi $cmd *, joka tietysti ajaisi komennon luettelo nykyisen hakemiston tiedostoista.
  • @ G-Man, lukuun ottamatta zsh, `cat` laajentaisi jo * (noteeraamaton $i voisi edelleen laajentaa jokerimerkkiä (toinen kierros), jos `cat` esittelee joitain). Joka tapauksessa tämä lähestymistapa on todellakin väärä.
  • +1. Tämä toimii hyvin, jos jokainen rivi sisältää vain syötteen, joka tarvitaan komennolle ilman välilyöntejä.
  • +1, tykkäsi xargs-ratkaisusta
  • Tämä toimii! (myöhempi muokkaus xargs -l COMMAND < file). Kiitos!

Vastaa

 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 

LÄHTÖ

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

Vastaa

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

Ota kaikki tiedoston rivit ja välittää ne argumentteina yhteen komentoon, ts.

command line1 line2 line3 .... 

Jos tarvitset --option jokaista riviä edeltävä lippu vaihtaa toisen komennon muotoon:

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

Kommentit

  • Mikä -1 käyttää ed … todella?
  • En ' äänestänyt sinua alhaalla, mutta henkilöllä, jolla oli todennäköisesti seuraavat syyt: (1) Tämä ei tee mitä kysymys kysyy. Tämä kutsuu komennon kerran ja koko tiedoston sisältö komentorivillä. pikemminkin kuin kerran riviä kohti .(2) Tämä ei tee mitään sellaisten merkkien käsittelemiseksi, jotka ovat erityisiä kuorelle (jotka voivat olla tiedostossa) esim. ', ", <, >, ; jne. (3) Tämä luo tarpeettoman väliaikaisen tiedoston. (4) Tällaiset asiat tehdään yleensä ”täällä asiakirjoilla”. (5) ed -komennosi ovat kömpelöitä; kaksi ensimmäistä komentoa voidaan pienentää muotoon %s/^/ / ja %j.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *