Yritän ilman menestystä käyttää awk -komentoa for -silmukka.
Minulla on muuttuja, joka sisältää sarjan merkkijonoja, jotka haluan leikata awk saada tietoja.
Tiedän miten se tehdään, mutta mitä todella haluan on leikata tiedot peräkkäin.
Joten sain tämän muuttujan:
var="data1,data2,data3"
Ja tässä missä olen tällä hetkellä:
for ((i=1; i<=3; i++)) do echo $(awk -F, "{print $1}" <<< $var) done
Yritän korvata $1 silmukan kautta $i, mutta ei menestystä.
Kommentit
Vastaa
Voit suorittaa uudestaan yrittää tehdä lisäämällä shell-muuttujan awk-komentosarjassa olevilla kaksoislainausmerkeillä. Haluat silti pitää siinä yhden kirjaimellisen $, jonka voit tehdä välttämällä sen kääntämällä vinoviivaa :
echo $(awk -F, "{print \$$i}" <<<$var)
Tämä laajentaa $i muotoon 1, 2 ja 3 kussakin iteraatiossa, joten awk näyttää $1, $2 ja $3 mikä saa sen laajentamaan kutakin kenttää.
Toinen mahdollisuus on injektoida shell-muuttuja awk-muuttuja -v -lipun avulla :
echo $(awk -F, -v i="$i" "{print $i}" <<<$var)
Tämä määrittää awk-muuttujan i saman nimisen shell-muuttujan sisältöön. Awk: n muuttujat eivät käytä $ -kenttää, jota käytetään kentissä, joten $i riittää viittaamaan i . kenttä, jos i on muuttuja awk-tiedostossa.
awk-muuttujan määrittäminen -v: n kanssa on yleensä turvallisempaa. lähestymistapa, varsinkin kun se voi sisältää mielivaltaisia merkkijonoja, siinä tapauksessa on pienempi riski, että sisältö suoritetaan awk-koodina aikomuksiasi vasten. Mutta koska sinun tapauksessasi muuttujalla on yksi kokonaisluku, siitä ei ole vähemmän huolta.
Vielä yksi vaihtoehto on käyttää for -silmukkaa itsessään awk . Katso awk-ohjeista (tai hae tältä sivustolta) lisätietoja siitä.
Kommentit
- … tai aseta syötetietue erotin asianmukaisesti
awk -v RS='[,\n]' 1 <<< "$var"(tai ehkä kannettavamminprintf "$var" | awk -v RS=, 1) - @steeldriver Tuo awk-skripti tulostaa kaikki kolme kenttää osoitteessa Mikä on kunnossa, kun OP tekee juuri sitä … päädyin keskittämään vastauksen yhden kentän purkamiseen oletukseen, että he olivat kiinnostuneita suorittamaan muita komentoja shell-silmukassa (mikä saattaa ovat olleet motivaationa sellaisen käyttämiselle ensiksi …)
- Ymmärretty – että ’ miksi kommentoin toimenpideohjelmaa selvittääkseen, mitä he todella haluavat tehdä;)
- ensimmäinen on injektio (ja turvallisuusongelma), toinen o ne (käyttämällä
-v) ei ole injektio. - Kiitos, vastauksesi ratkaisi ongelmani! Ensimmäisen kerran lähetän kysymyksen tähän vuosien lukemisen jälkeen. Ei pettynyt. Tällainen loistava yhteisö!
Vastaa
Käyttämällä awk näyttää liiallinen tässä tilanteessa, entä tr ja while-loop:
tr , "\n" <<<"$var" | while read; do echo $REPLY done
Lähtö:
data1 data2 data3
Kommentit
- Hienoa.
REPLYoletusarvoinenname-argumenttireadsisäänrakennetulle komentokomennolle. - Huomaa, että tämä edellyttää, että kuori käyttää oletusmuuttujaa tietojen sijoittamiseen kohteesta
read, mikäbashsattuu tekemään , mutta tämä ei ole vakio. Myösread-komentosi voi muokata tietoja, jos se sisältää taaksepäin osoittavia viivoja, ja voi poistaa reunan reunan tyhjät tilat arvoista. Se lukisi myös arvot upotetuilla uusilla viivoilla useina arvoina. Tarvitset lisäksi"$REPLY"estääksesi kuoren jakamasta arvoa ja suorittamasta tiedostonimen laajennusta siihen.
vastaus
awk voi hyväksyä sekä j (muuttujana) että $j (kenttäindeksinä):
for i in 1 2 3; do echo "$var" | awk -v j=$i -F , "{print $j}"; done
$i esimerkissä” sekava ”awk mitä käyttää (kuori tai oma muuttuja – etusijalla), koska molempiin viitataan $ -etuliitteellä.
muistiinpano
sh -sarja, joka on vakio ”kannettaville” komentosarjoille, ei tue:
(( i=1; i<=3; i++; )) ja <<< $var rakentaa
Voit myös harkita seq -komennon käyttämistä for -silmukka tarkempaan hallintaan numerosarjojen luomisessa, jos käytettävissä.
Kommentit
- Silmukka toimisi vain, jos satunnaisesti kutsutaan kolme tiedostoa ,
2ja3nykyisessä hakemistossa. Käytät myös muuttujan laajennusta, jota ei ole mainittu kuoressa ja jolla voi olla ei-toivottuja seurauksia, jos tiedot sisältävät tiedostonimikuvioita (kuten*).echovoi lisäksi muokata tietoja, jos se sisältää taaksepäin viivoja.
Vastaa
#!/bin/sh var="data1,data2,data3" unset data while [ "$var" != "$data" ]; do data=${var%%,*} # delete first comma and the bit after it var=${var#*,} # delete bit up to first comma (and the comma) printf "data = "%s"\n" "$data" done
Tässä muuttujakorvikkeita käytetään saamaan kukin peräkkäinen pilkulla erotettu tietokenttä muuttujan var arvosta. Silmukan ensimmäinen tehtävä data -kohtaan poistaa kaiken $var -kohdasta ensimmäisen pilkun jälkeen. Muuttujaa var muutetaan sitten siten, että ensimmäinen bitti ensimmäiseen pilkkuun asti poistetaan.
Tämä jatkuu, kunnes "$var" = "$data" mikä tarkoittaa, että merkkijonolle ei voida tehdä mitään muuta.
Tämä tapa tehdä se antaisi meille mahdollisuuden käsitellä pilkuilla erotettuja tietojonoja, jotka sisältävät upotettuja uusia rivejä:
var="line1 line2,data2,last bit goes here"
Jos yllä olevilla arvoilla on var, yllä oleva komentosarja tuottaisi
data = "line1 line2" data = "data2" data = "last bit goes here"
Ei välitä upotetuista uusista viivoista; hyvin harvoin sinun on siirryttävä awk -kehotusten yli.
Huomaa, että awk lukee merkkijonon mielellään pilkulla erotettujen kenttien joukoksi ja pystyy silmukkaamaan näitä:
printf "%s\n" "$var" | awk -F "," "{ for (i=1; i<=NF; i++) print $i }"
Kanssa var="data1,data2,data3", tämä tulostaa
data1 data2 data3
Toinen kuoriratkaisu, joka käyttää IFS -muuttuja jakamaan $var -arvo bitteihin ja samalla käyttämään set -f -toimintoa tiedostonimen laajennuksen poistamiseksi käytöstä:
set -f oldIFS=$IFS; IFS="," set -- $var IFS=$oldIFS; unset oldIFS set +f for data do printf "data = "%s"\n" "$data" done
echo "${var//,/$'\n'}")