Van fájl.txt fájlom, amelyet be kell olvasnom egy Bash tömbbe. Ezután el kell távolítanom a szóközöket, a dupla idézőjeleket és az összes vesszőt kivéve az összes vesszőt . Itt van, milyen messzire jutottam:
$ 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|
A vesszőhelyzet kivételével ez remekül működik. Tisztában vagyok vele, hogy többféle módon lehet megnyúzni ezt a macskát, de a nagyobb szkript miatt ez része, nagyon szeretnék a paraméterekkel helyettesíteni az idejutást:
|ELEMENT|10,this| |ELEMENT|20,is| |ELEMENT|30,all| |ELEMENT|40,I| |ELEMENT|50,need2| |ELEMENT|60,see|
Lehetséges ez a paramétercsere révén?
Megjegyzések
- Van valami oka annak, hogy a szöveget bent kell tartani egy tömböt, és miért ‘ nem engedheti meg pl.
awk
vagysed
végzi az adatok feldolgozását? - @Jeff – A tömbhöz való hurkolás a rémálom, amelyet a nagyobb szkriptben megvalósítok, én ‘ m dolgozom.
- @JonRed nem tudom ‘ csinálsz, tehát ‘ teljesen lehetséges, hogy lehet, hogy nincs választási lehetőséged az ügyben, de általában, amikor olyan összetett húrakrobatikát folytatsz a shellben, hogy ‘ nagyon jól jelzi, hogy egy tényleges programozási nyelvet kell használnia. A shell nem programozási nyelvként van megtervezve, és bár használható egyként, valójában nem ‘ nem jó ötlet bonyolultabb dolgokhoz. Erősen sürgetem, hogy fontolja meg a váltást a perlre vagy a pythonra, vagy bármely más szkript nyelvre.
- @terdon Ez ‘ s vicces, épp most mondtam el a pontos mondást ugyanezt kollégámnak, mielőtt elolvastam ezt a bejegyzést. Alapvetően azt mondtam, hogy ez a szkript végleges verziója, és hogy minden további követelmény szükségessé teszi a Perl-ben történő újbóli írást. Tehát igen, határozottan egyetértek
Válasz
A sed
mielőtt a tömbbe töltődik (vegye figyelembe a kisbetűs változóneveket is, általában a legjobb elkerülni a nagybetűs változókat a shell parancsfájlokban):
#!/bin/bash readarray -t array< <(sed "s/"//g; s/ *//g; s/,/"/; s/,//g; s/"/,/" "$1") for element in "${array[@]}";do echo "|ELEMENT|$element|" done
Ez a következő kimenetet eredményezi a példafájlban:
$ foo.sh file |ELEMENT|10,this| |ELEMENT|20,is| |ELEMENT|30,all| |ELEMENT|40,I| |ELEMENT|50,need2| |ELEMENT|60,see|
Ha valóban használni kell a paramétert cserével próbálkozzon valami ilyesmivel:
#!/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
Megjegyzések
Válasz
Amennyire látom, nem kell olvassa el egy bash
tömbbe a kimenet létrehozásához:
$ 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|
A sed
kifejezés törli a szóközöket és a dupla idézőjeleket, az első vesszőt szóközzel helyettesíti (ezen a ponton nincsenek más szóközök a karakterláncban), az összes többi vesszőt törli, az első vesszőt visszaállítja, és az előkészíti és hozzáfűzi az extra adatokat .
Alternatív megoldásként a GNU sed
:
sed "s/[ "]//g; s/,//2g; s/.*/|ELEMENT|&|/" <file
(standard sed
nem támogatja a 2
és g
kombinációt a parancs).
Megjegyzések
- a GNU sed használatával használhatja a
's/,//2g
vessző eltávolításához, kezdve a 2. - És az utolsó 2 s /// parancs lehet
s/.*/|ELEMENT|&|/
de ez nagyobb erőfeszítést jelenthet a sed számára. - @glennjackman Esetleg, de meglehetősen ügyesnek tűnik.
- Igen, ez egy nagyobb szkript része. A tömb szükséges, nem csak a kimenethez. Ezért érdeklődöm a paraméterek helyettesítése iránt. Ezzel át tudnám hurkolni a tömböt, de ezt rémálom lesz megvalósítani. Terndon egy hurok nélküli megoldást nyújtott a sed használatával, amellyel valószínűleg I ‘ visszaesem, ha a paraméter-helyettesítés tilos.
- Ha nem voltam = “fb841fb5b8”>
nem egy tömb használatához kötött, de ez lenne a legjobb megoldás.
Válasz
ELEMENT="50,n,e,e,d,2" IFS=, read -r first rest <<<"$ELEMENT" printf "%s,%s\n" "$first" "${rest//,/}"
50,need2
Lépjen ki az ALLCAPS változónevek használatának szokásából. Végül összeütközik egy olyan fontos “rendszer” változóval, mint a PATH, és megtöri a kódját.
Megjegyzések
- Nem paramétercsere. DE, nem tudtam, hogy az ALLCAPS változónevek rossz szokás Bash-ban. Ön jó észrevételt tesz, amelyet egy felületes guglizás mindenképpen megerősít. Köszönöm, hogy javítottad a stílusomat! 🙂
- Én ‘ válaszoltam azokra a kérdésekre, ahol az illető írt
PATH=something; ls $PATH
, majd kíváncsi voltam als: command not found
hiba. - Közel száz beépített változó van, amelyeket minden nagybetűvel elneveznek (kattintson ezen a man oldalon link ), hogy lássa …
Válasz
[Ez lényegében egy fejlettebb glenn jackmann válaszának változata ]
Asszociatív tömb építése a lecsupaszított kulcsból és értékből, az első vessző elválasztóként történő felhasználásával:
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|
Válasz
Áthúzhatja a tömböt, és használhat egy köztes változót:
for((i=0; i < "${#ARRAY[@]}"; i++)) do rest="${ARRAY[i]#*,}" ARRAY[i]="${ARRAY[i]%%,*}","${rest//,/}" done
Ez hozzárendeli a rest
-hez az első vessző utáni részt; ezután három darabot összefűzünk az eredetibe változó:
- az első vessző előtti rész
- vessző
- minden vessző cseréje a
rest
ben semmivel
Megjegyzések
- Ez volt az első gondolatom, és elég egyszerű a példához, de ez egy nagyobb szkript része, ahol a tömb masszív és ‘ s már hurkol, és ez egy egész dolog lenne. Ez mindenképpen működne, de nagyon nehézkes lenne megvalósítani a nagyobb projektben, amelyen én ‘ m dolgozom.
- Elég korrekt; Csak korlátozásokon belül próbáltam válaszolni (csak a paraméterek bővítése).
RANDOMTEXTTHATWILLNEVERBEINTHEFILE
helyett.