Parametrikorvauksen käyttäminen Bash-taulukossa

Minulla on tiedosto.txt, joka minun täytyy lukea Bash-taulukoksi. Sitten minun on poistettava välilyönnit, lainausmerkit ja kaikki paitsi ensimmäinen pilkku jokaisesta merkinnästä . Tässä kuinka pitkälle olen päässyt:

$ cat file.txt 10,this 2 0 , i s 30,"all" 40,I 50,n,e,e,d,2 60",s e,e" $ cat script.sh #!/bin/bash readarray -t ARRAY<$1 ARRAY=( "${ARRAY[@]// /}" ) ARRAY=( "${ARRAY[@]//\"/}" ) for ELEMENT in "${ARRAY[@]}";do echo "|ELEMENT|$ELEMENT|" done $ ./script.sh file.txt |ELEMENT|10,this| |ELEMENT|20,is| |ELEMENT|30,all| |ELEMENT|40,I| |ELEMENT|50,n,e,e,d,2| |ELEMENT|60,se,e| 

Mikä toimii hyvin pilkkuja lukuun ottamatta. Olen tietoinen siitä, että on olemassa useita tapoja nylkeä tämä kissa, mutta suuremman komentosarjan vuoksi tämä on osa, haluaisin todella käyttää parametrien korvaamista päästäksesi tänne:

|ELEMENT|10,this| |ELEMENT|20,is| |ELEMENT|30,all| |ELEMENT|40,I| |ELEMENT|50,need2| |ELEMENT|60,see| 

Onko tämä mahdollista parametrien korvaamisen avulla?

Kommentit

  • Onko sinun syytä pitää teksti taulukkoa ja miksi ’ ei saa antaa esim. awk tai sed käsittelevätkö tietoja?
  • @Jeff – Taulukon silmukkaaminen on painajainen, joka toteutetaan suuremmassa komentosarjassa, ’ m työskentelen.
  • @JonRed En tiedä mitä ’ teet, joten ’ on täysin mahdollista, että sinulla ei ehkä ole valinnanvaraa asiassa, mutta yleensä, kun huomaat harrastavansi niin monimutkaista merkkijonoakrobatiaa kuoressa, että ’ on erittäin hyvä osoitus siitä, että sinun tulisi käyttää todellista ohjelmointikieliä. Kuorta ei ole suunniteltu ohjelmointikieleksi, ja vaikka sitä voidaan käyttää yhtenä, se ei todellakaan ole ’ t hyvä idea monimutkaisemmille asioille. Kehotan teitä harkitsemaan vaihtamista perl-, python- tai mihin tahansa muuhun komentosarjakieleen.
  • @terdon It ’ on hauskaa, sain vain sanoa melkein tarkan sama asia kollegalleni ennen kuin luin tämän viestin. Sanoin pohjimmiltaan, että tämä on tämän komentosarjan lopullinen versio ja että kaikki uudet vaatimukset edellyttävät uudelleen kirjoittamista Perliin. Joten kyllä, olen ehdottomasti samaa mieltä

vastaus

Poistaisin poistettavat tiedot käyttämällä sed ennen lataamista taulukkoon (huomioi myös pienten muuttujien nimet, yleensä on parasta välttää isoja kirjaimia muuttujista shell-komentosarjoissa):

#!/bin/bash readarray -t array< <(sed "s/"//g; s/ *//g; s/,/"/; s/,//g; s/"/,/" "$1") for element in "${array[@]}";do echo "|ELEMENT|$element|" done 

Tämä tuottaa seuraavan tuloksen esimerkkitiedostoon:

$ foo.sh file |ELEMENT|10,this| |ELEMENT|20,is| |ELEMENT|30,all| |ELEMENT|40,I| |ELEMENT|50,need2| |ELEMENT|60,see| 

Jos sinun on todella käytettävä parametria kokeile jotain tällaista:

#!/bin/bash readarray -t array< "$1" array=( "${array[@]// /}" ) array=( "${array[@]//\"/}" ) array=( "${array[@]/,/\"}" ) array=( "${array[@]//,/}" ) array=( "${array[@]/\"/,}" ) for element in "${array[@]}"; do echo "|ELEMENT|$element|" done 

kommentit

  • @JonRed Lisäsin version parametrilla korvaaminen, mutta se ’ on monimutkainen, hankala ja ruma. Tällaisen tekeminen kuoressa on hyvin harvoin hyvä idea.
  • Huomaa, että jos olet ’ poistanut sekä välilyönnit että lainausmerkit, nämä merkit ovat käytettävissä käyttää RANDOMTEXTTHATWILLNEVERBEINTHEFILE -tunnuksesi sijaan.
  • @Kusalananda joo, luin vastauksesi. Olisi pitänyt ajatella sitä! Kiitos 🙂
  • Vastaa suoraan kysymykseen, havainnollistaa, miksi suosimani ratkaisu ei ole ’ ihanteellinen, ja tarjoaa toteuttamiskelpoisimman vaihtoehdon. Voitat, paras vastaus.

Vastaa

Sikäli kuin näen, ei ole tarvetta luo se bash -taulukkoon kyseisen tuotoksen luomiseksi:

$ sed "s/[ "]//g; s/,/ /; s/,//g; s/ /,/; s/.*/|ELEMENT|&|/" <file |ELEMENT|10,this| |ELEMENT|20,is| |ELEMENT|30,all| |ELEMENT|40,I| |ELEMENT|50,need2| |ELEMENT|60,see| 

sed -lauseke poistaa välilyönnit ja lainausmerkit, korvaa ensimmäisen pilkun välilyönnillä (merkkijonossa ei ole muita välilyöntejä tässä vaiheessa), poistaa kaikki muut pilkut, palauttaa ensimmäisen pilkun ja valmistelee ja liittää ylimääräiset tiedot .

Vaihtoehtoisesti GNU: lla sed:

sed "s/[ "]//g; s/,//2g; s/.*/|ELEMENT|&|/" <file 

(vakio sed ei tue 2 – ja g -yhdistelmää lipuina s -komento).

Kommentit

  • GNU sedin kanssa voit käyttää 's/,//2g poistaa pilkkuja, alkaen toisesta
  • Ja viimeiset 2 s /// -komennot voivat olla s/.*/|ELEMENT|&|/ mutta se voi olla enemmän vaivaa sedille.
  • @glennjackman Mahdollisesti, mutta se näyttää melko siistiltä.
  • Joo, tämä on osa suurempaa komentosarjaa. Matriisi on välttämätön, ei vain lähtöä varten. Tästä syystä olen kiinnostunut parametrien korvaamisesta. Voisin silmukata taulukon yli tällä, mutta se on painajainen toteuttaa. Terndon toimitti silmukkavapaan ratkaisun käyttäen sed, että I ’ palaan todennäköisesti takaisin, jos parametrin korvaaminen on kiellettyä.
  • Jos minua ei ollut ’ ei sidottu matriisiin, tämä olisi kuitenkin paras ratkaisu.

Vastaa

ELEMENT="50,n,e,e,d,2" IFS=, read -r first rest <<<"$ELEMENT" printf "%s,%s\n" "$first" "${rest//,/}" 
50,need2 

Poista ALLCAPS-muuttujien nimistä. Lopulta törmäät tärkeän ”järjestelmä” -muuttujan, kuten PATH, kanssa ja rikkot koodisi.

Kommentit

  • Ei parametrien korvaamista. MUTTA, en tiennyt, että ALLCAPS-muuttujien nimet olivat huono tapa Bashissa. Teet hyvän asian, jonka päällekkäinen googling varmasti vahvistaa. Kiitos tyylini parantamisesta! 🙂
  • Olen ’ vastannut kysymyksiin, joihin henkilö kirjoitti PATH=something; ls $PATH ja sitten ihmettelin ls: command not found -virhe.
  • Lähes sata sisäänrakennettua muuttujaa on nimetty kaikissa kirjaimissa (napsauta

tätä man-sivua linkki ) nähdäksesi …

Vastaa

[Tämä on pohjimmiltaan kehittyneempi versio glenn jackmannin vastauksesta ]

Assosiatiivisen taulukon rakentaminen irrotetusta avaimesta ja arvosta käyttämällä ensimmäistä pilkkua erottimena:

declare -A arr while IFS=, read -r k v; do arr["${k//[ \"]}"]="${v//[ ,\"]}"; done < file.txt for k in "${!arr[@]}"; do printf "|ELEMENT|%s,%s|\n" "$k" "${arr[$k]}" done |ELEMENT|20,is| |ELEMENT|10,this| |ELEMENT|50,need2| |ELEMENT|40,I| |ELEMENT|60,see| |ELEMENT|30,all| 

vastaus

Voit siirtyä matriisin yli ja käyttää välimuuttujaa:

for((i=0; i < "${#ARRAY[@]}"; i++)) do rest="${ARRAY[i]#*,}" ARRAY[i]="${ARRAY[i]%%,*}","${rest//,/}" done 

Tämä osoittaa rest -osan ensimmäisen pilkun jälkeen; liitämme sitten kolme kappaletta takaisin alkuperäiseen muuttuja:

  • ensimmäinen pilkku edeltävä osa
  • pilkku
  • jokaisen pilkun korvaaminen rest -kohdassa ilman mitään

kommentteja

  • Tämä oli ensimmäinen ajatukseni ja se on tarpeeksi yksinkertainen esimerkkiä varten, mutta tämä on osa suurempaa komentosarjaa, jossa taulukko on massiivinen ja siellä ’ on jo silmukoita ja se olisi koko juttu. Tämä toimisi ehdottomasti, mutta olisi erittäin hankalaa toteuttaa suuremmassa projektissa, jonka parissa ’ työskentelen.
  • Riittävän oikeudenmukainen; Yritin vain vastata rajoitusten puitteissa (vain parametrien laajentaminen).

Vastaa

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