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.
REPLY
oletusarvoinenname
-argumenttiread
sisäänrakennetulle komentokomennolle. - Huomaa, että tämä edellyttää, että kuori käyttää oletusmuuttujaa tietojen sijoittamiseen kohteesta
read
, mikäbash
sattuu 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 ,
2
ja3
nykyisessä 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*
).echo
voi 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'}"
)