script kérdés

Mi lesz, öreg koromra, ha már most is teljesen elhülyülök?
A legegyszerűbb dolgokra sem emlékszem.

Van egy fájlom, benne sorok, és a sorokban szóközzel elválasztva szavak (path/fájlnév).

Szeretnék egy ciklust, ami végigmegy a sorokon.

aztán eltároljuk az első nevet,
majd egy belső ciklusban végig az összes többin.

Holt egyszerű. Csak nem emlékszem, hogy is kellene nekilátni.
Odáig eljutottam, hogy while read line; valami $line; done < file
Valószínű egy for ciklussal végig tudok menni az összes szón, de nem tudom, hogy vegyem ki az elsőt.

Ha majd össze is áll, félek, mi lesz az eredmény :-)

Szóval útmutatást szeretnék. Esetleg azt, hogy kellett volna jobban megcsinálni.

Hozzászólások


#!/bin/bash

IFS=' '

while read first second; do
  echo ">>>$first"
  echo "+++$second"
done < "$1"

---%<---


$ x.sh x.sh
>>>#!/bin/bash
+++
>>>
+++
>>>IFS='
+++'
>>>
+++
>>>while
+++read first second; do
>>>echo
+++">>>$first"
>>>echo
+++"+++$second"
>>>done
+++< "$1"

Áh... a read úgy működik, hogy megadhatsz neki egy vagy több változónevet, és azokba teszi az IFS által meghatározott szavakat, illetve az utolsóba a maradékot.

Ezt én úgy szoktam használni, hogy ha adott egy csv pl:

:Kiss:János:asztalos:

Akkor ezt négy változóba olvasom be (vezeték- és keresztnév, beosztás, garbage) és ha van, akkor az utolsóba teszi a szemetet.

Így valóban nem volt tökéletes. Ha egy sorban legalább három szóközöket is tartalmazó elérési út szerepelt, akkor az első még jó volt, de a read az escape-eket kiszedte, és így a maradékot nem lehetett rendesen szétvágni.

Végül, ahogy javasoltad, tömböt használtam.

Ez lett a végeredmény:


while read -a two; do
        one="${two[0]}"
        unset two[0];
        for i in "${two[@]}"; do
                rm "$i"
                ln "$one" "$i"
        done
done < $1

Az eredménnyel elégedett vagyok, hiszen működik, de a shell tömb kezelését megtanulni hozzá az kicsit több volt, mint amire számítottam.
Azt hittem egyszerűbben (új dolog megtanulása nélkül) is meg lehet oldani.

Lehet, hogy pythonban kellett volna megírnom, csak éppen feltételeztem, hogy shell scriptben hipp-hopp megvan, ha sikerül visszaemlékeznem a dolgokra.

"Azt hittem egyszerűbben (új dolog megtanulása nélkül) is meg lehet oldani."

Nem mondom, hogy szépen (és itt meg a fájlnevekben előforduló aposztrófok okoznának gondot), de lehet.


while read -r all; do
   [ -z "$all" ] && continue
   all=`echo "$all" | sed -e 's/\\\\ /@@szokoz@@/g'`
   set -- $all
   FIRST=`echo $1 | sed -e 's/@@szokoz@@/ /g'`; shift
   while [ $# -gt 0 ]; do
      NEXT=`echo $1 | sed -e 's/@@szokoz@@/ /g'`; shift
      echo "ln -f '$FIRST' '$NEXT'"
   done
done < txt

Persze.
Mondjuk, akkor az volna a kérdés, hogy melyik letöltő/böngésző van annyira elcseszve/kiokosítva, hogy juszt is URL-kódolva írta az általa leszedett fájlok nevét.

Ahogy egy kolléga utalt rá, shellben humán felülvizsgáló nélkül eléggé végtelenbe nyúlik az ilyen történet.

Éppen ezért amikor (ötévente egyszer) kócos fájlneveket fésülök, mindig legenerálom a vonatkozó szkriptet, abból kigrepelem azt a néhányat, ami annyira egzotikus, hogy kézzel biztosabb elbánni vele, a maradék meg marad a szkriptben és chmod 700, ./fussahogytudsz.

Izé... mi lenne a kívánt végeredmény? Mert szerintem félreértem:

in.txt:


path file name
path2 file2 name
path3 file name3

script.sh:


#!/bin/bash

while read Line
do
 for Word in ${Line}
 do
  echo -n \""${Word}"\"\
 done
 echo ""
done < in.txt

A vég és eredmény:


fisher@ap:/tmp$ ./script.sh
"path" "file" "name"
"path2" "file2" "name"
"path3" "file" "name3"

Ez ugyan nem pontosan az, amit akarsz (hadd ne oldjam meg helyetted ;) ) de talán segít:

IFS=':' ; cat /etc/passwd | while read -a a ; do echo "---" $a "---" ; for i in "${a[@]}" ; do echo "." $i ; done ; done

Lényeg, hogy IFS-ben meg kell adni, mi legyen a mező szeparátor, a read -a tömbbe olvassa az egyes sorokat, a for ... in "${tomb[@]}" meg végigmegy az egyes tömbelemeken.

Esetedben az első elem a [0] lesz, ezt valahogyan el kellene távolítani a tömbből, mielőtt for-ral végigmész rajta, de arra már nem emlékszem, hogy azt hogy kell. Talán pop? Rég volt, én sem emlékszem.