Ciklusban olvasod soronként, és minden 24. után beiktatsz egy read-et.
Jester
Ciklusban olvasod soronként, és minden 24. után beiktatsz egy read-et.
Jester
ez OK, de a head az mindig az állomány első X sorát írja ki. Szóval ha az első ciklus lefut, akkor a következőben megint csak az első 24-et írná ki.
Headet felejtsd el. Simán olvasd be egy shell ciklusban egyesével a sorokat (read) és írasd ki (echo).
Jester
én itt keresgéltem a read-del kapcsban, de nem tudom hogy érted. Fájlból hogy olvassak be a read-del soronként?
A read-et csak úgy ismerem, hogy ENTER leütéséig olvassa a leütött karaktereket a Standard inputról. Ha átirányítom egy fájlba read > fájl, akkor beleírja. vagy vhogy így.
Te ezt hogy gondolod, mert én nemtom.
közben azért próbálkozom.
[Szerkesztve]
Igen, a read a standard inputról olvas, enterig. Viszont az átirányítással éppen a standard inputhoz rendelhetsz másik fájlleírót.
Csak éppen a másik irányba kell átirányítani: read < file
(Persze ciklusban kicsit másképp.)
Jester
bocs, de nekem ez a retek eccerű script se fut le:
echo ''peldaprogi'' $(read < ize.txt)
természetesen előtte van a #! /bin/bash
Ez nem is. A read az változó(k)ba olvas. A te példád is beolvasott egy sort, csak aztán eldobta. Helyesen:
read sor < ize.txt
echo $sor
Jester
igazad van, le is esett.
Viszont most olyan problémám van, hogy minden egyes alkalommal csak 1 sort olvas be a read:
#! /bin/bash
COUNT=0
while [ $COUNT -lt 2 ]
do
read sor < $1
echo $sor
COUNT=$(($COUNT+1))
done
azért 2-ig megy a count, mert kis fájlon tesztelem. Ha működni fog arra hogy kettessével irogassa Enterenként, akkor átírom 24-re.
Mert itt már a while-nak (illetve az azt futtató alshellnek) kell megadni az átirányítást.
while [ $COUNT -lt 2 ]
do
read sor
echo $sor
COUNT=$((COUNT+1))
done < $1
MOD: Illetve kezdők jobban szokták szeretni a cat $1 | while ... formát mert jobban átlátható. Viszont indít egy fölösleges cat processzt.
[Szerkesztve]
Jester
Ez zsír. A fájl végét hogy vizsgálom? Azért kérdem, mert úgy képzeltem el, hogy
while !(fájl vége)
do
while [ $COUNT -lt 2 ]
do
read sor
echo $sor
COUNT=$((COUNT+1))
done < $1
read
done
[Szerkesztve]
Ez így nem lesz jó, mert a belsõ ciklus mindig újrakezdi a fájl olvasását az elejérõl.
Szóval mindenképpen az a while read sor kell kívülre. Belül meg simán csak számolod a sorokat, és 24 után egy if segítségével vársz egy entert és nullázod a számlálót. Még lesz vele egy kis gubanc, mégpedig az, hogy az entert váró read is a már átirányított fájlból akar majd olvasni. Szóval azt meg vissza kell irányítani a terminálra Ehhez célszerû elmenteni a ciklus elõtt az stdin fájlleíróját, és a belsõ readnek megadni. Olvasd el a man bash átirányításról szóló részét, különös tekintettel a fájlleirók másolására.
Jester
atya-gatya...lehet kezdünk mélyre ásni. Ezt már csak holnap este tom megnézni. De amúgy nagyon köszi!
uh, kicsit sokáig voltam Pesten, tovább mint terveztem. Most jöttem, és van most is 1 kérdésem:
Ez mit jelent:?
IFS=$'\\\\n'
Ebben szerintem kicsit sok a backslash.
Az IFS egy shell beépített változó, ami a mezőhatárokat adja meg, pl. a read parancs esetén, illetve összefűzéseknél.
Jester
nem mondom h teljesen értem, de innen szedtem: [link]
mod.: gáz van. Nemtok be SSH-zni suliba megnézni a bash manuálját, hogy lehet ezt megcsinálni: Ehhez célszerû elmenteni a ciklus elõtt az stdin fájlleíróját, és a belsõ readnek megadni.. Neten fent van magyarul?
most linuxot nincs kedvem letölteni (live), feltelepíteni meg végképp nem is tudnék hely hiányában.
[Szerkesztve]
van egy ilyen kis szkriptem:
#!/bin/bash
rm -rf mp3dir
stdir=`pwd`
koz=''_''
mkdir mp3dir
mpdir=$stdir/mp3dir
k=0;
find . | grep \.mp3$ | sort > mp3list.txt
i=`wc -l mp3list.txt | cut -d'' '' -f1`
for j in `seq -w $i `
do
mpfile=`cat mp3list.txt | head -n $j | tail -n 1;`
mp=`basename ''$mpfile''`
cp ''$mpfile'' $mpdir/''$j$koz$mp''
done;
működik rendesen (mp3-albumokat sorszámoz, és 1 kt-ba pakolja. egyes mp3-lejátszóknál jól jön), csak nem túl elegáns, hogy mindig létrehoz egy mp3list.txt állományt. meg lehet-e oldani, hogy ne egy file-on keresztül kelljen sorbapakolni a file-okat, hanem pl. egy változóba, vagy valami hasonló, memóriában helyet foglaló cuccban? vagy ha úgy macerás, akkor egy tmp-file-ba (tehát szabályosan kezelje a /tmp könyvtárat, véletlenszerű névvel)?
Na ezt most nem értem. Neked az a fájl nem kell a végén? Mert akkor elég ha átirányítod a null-ba, és semmi nyoma nem marad.
Szerintem ezt embertelenül elbonyolítottad
Ha fixen tudod hány számjeggyel szeretnél sorszámozni akkor ez kb. ennyi:
j=1
find . -name '*.mp3' | sort |
while read mpfile
do
cp ''$mpfile'' ...
j=$((j+1))
done
Jester
na ez az! köszi.
a szkript kb. 1 éve kezdődött, eddig 5 verziót élt meg, és közel 0 szkriptelési tudással kezdtem neki.
az eredeti ''probléma'' az is volt, hogy nem tudom, hány számjeggyel számozom a file-okat, de ez a legtöbb esetben 3. a seq -w is emiatt került bele, azelőtt egy 3-részes if-sorozat volt benne, de az annyira gányul nézett ki, hogy szörnyű
most is igaz, hogy a legegyszerűbb dologra nem gondoltam, pontosabban ezt a módszert nem ismertem.
Akkor itt egy kis trükk, hogyan lehet ifek nélkül 0val azonos hosszra kitölteni számokat:
Inicializálás:
last=999
len=${#last}
zeroes=${last//[0-9]/0}
$i kipótlása:
tmp=''$zeroes$i''
padded=${tmp: -len}
MOD: az utolsó sorba a : után szóköz kell!
[Szerkesztve]
Jester
ehh, ez nekem már magas... lehet, hogy annak idején mégiscsak fel kellett volna vennem a progmatot a vegyészet mellé?
Nos, van egy kezdeményezésem a megoldásra, amit most nem áll módomban letesztelni.
#! /bin/bash
if test -f $1;
then
_____HOSSZ=`wc -l $1`
_____for ((i=1; i!= $[$HOSSZ+1]; ++i))
_____do
_____head -n $i | tail -n1
_____if [ $i -ge 2 ]; then
__________read
__________clear
_____fi
_____done
else echo ''Nem fájl!''
_____exit
fi
ps.: hiába rakom kódba, a szóközt/tabulálást nem tartja meg, de miért
Kérdésem: hol fog ez megbukni? Csak mert amennyire ismerem magam tuti nem fog műxeni
Az a bash mélységeibe vájós dolog nekem lehet nem menne, és most nem is tudnám meg se nézni, mert bexart a suliban a server, vagy csak szarakodnak velünk (ált. ZH előtt csinálnak vele vmi gubancot, vagy kötprog leadások előtt, hogy a hallgatónak esélye se legyen befejezni időben lassan azt kell hinnem ezt direkt csinálják)
[Szerkesztve]
Nézd meg ngabor2 szkriptjét, a wc sajnos gonosz módon kiírja a fájl nevét is. Szóval a sorszámoláshoz kell a cut is.
A ciklusban nyilván nem jó a $i -ge 2 feltétel (még akkor sem ha az ott tkp 24 akart lenni), hiszen így az első képernyő után már soronként várná az entert.
A for ciklusba a $[$HOSSZ + 1] helyett simán $HOSSZ + 1 kell (vagy egyszerűen i <= $HOSSZ ugye). A head után hiányzik a fájlnév ($1).
MOD: a szóközt tartalmazó fájlok helyes kezeléséhez a megfelelő helyeken idézőjelbe kell tenni a $1-et.
[Szerkesztve]
Jester
Van egy elméleti megoldásom. Félig vna csak shell-ben, mert nem volt időm buszon átnézni a szintaktikát (és gyorsan felejtek), de szerintem érthető lesz így is mit akartam.
Íme:
K=wc -l
x=1
for i=1 to K
do
if X<25
head -n i szoveg | tail -n 1 #ez tuti azt csinálja, h minden sort egyesével kiír.
x++
fi
read
X=1
rof
Tudom sok a szintaktikai hiba, de most csak az algoritmus helyessége a lényeg. Ha jó, akkor átírom amint lesz időm, csak holnap egy másik tárgyból ZH-zom. Ezt meg holnap estig kell leadjam.
[Szerkesztve]
nah, átírtam shell scripté, kijavítottam pár apróságot:
K=wc -l $1
x=1
for ((i=1;i<=k;i++))
do
if $[ x -lt 25 ]
head -n i szoveg | tail -n 1 #ez tuti azt csinálja, h minden sort egyesével kiír.
x=x+1
fi
read
x=1
done
Ez sajnos még mindig nem jó
Amit a wc-vel kapcsolatban írtam, azt nem vetted figyelembe.
A sor kiírás az if elé kell, hiszen azt mindig meg kell csinálni.
A head-bõl kimaradt a $ jel az i elõl, illetve a szoveg helyett $1 kell.
Az if-ben rossz helyen van a $ jel, helyesen if [ $x -lt 25 ] és kimaradt a then.
Az x=x+1 helyesen x=$((x+1))
A read elõtti fi az gondolom inkább egy else, és a fi a done elé való.
k=`wc -l ''$1'' | cut -d\ -f1`
x=1
for ((i=1;i<=k;i++))
do
head -n $i ''$1'' | tail -n 1 #ez tuti azt csinálja, h minden sort egyesével kiír.
if [ $x -lt 25 ]
then
x=$((x+1))
else
read
x=1
fi
done
Jester
Ok!
bocs, a szoveg benne maradt véletlen ezt a sort másoltam.
asszem a $ jel elírás volt részemről.
Köszi, remélem mostmár jó lesz.
ps: kirpóbáltam és ilyet kaptam:
cut: invalid delimiter
Ez milyen hiba?! még sose kaptam ezt
[Szerkesztve]
a delimiter határolójelet jelent. Mostmár ezt is tudom. De legalább a hibás sort számát kiírhatná a linux shellje.
ps:
head -n $i ''$1'' | tail -n 1
ebben a ' ' az miért két karakter és miért nem egy: '' Igaz ugyanúgy néznek ki, de nem mind1 melyiket mikor használjuk. Ez itt jó?
ps2: már látom. valszeg ez lesz a hiba. A PH motorja az idézőjelet két karakterér bontja, vagy az XP vágólapja rosz. Kipróbálom sima idézőjellel, bár nem tudom ide miért is kell.
ps3: ja, mert a fájlban szóközök is lehetnek.
[Szerkesztve]
bocs, de megint lejárt a módosítási időlimit.
Ugyanazt a hibát kaptam.
cut: invalid delimiter
Igen, a ph! a ludas ebben
A delimiteres hiba a cut-os sorban van, az ott -d\<szóköz><szóköz>-f1 lenne.
Jester
tényleg, mivel a sok szóközből 1et csinál mindig. De amúgy a code mód miért nem működik, régen ment vele rendesen a kód. nem vágta ki a tab-okat.
Amúgy oda miért kell 2 szóköz?
Amúgy a cut:...nál a cut-ra nem úgy néztem mintha a ódban lenne, hanem aztem a hibamagyarázás része. és mivel még linux buherátor sem vagyok, ezért aztem ilyen szűkszavú a linux, mint mindig is volt.
téháX
most try-olom.
ps: trájoltam, de ez az eredmény copy-ja:
rozi> chmod +x proba.sh
rozi> ./proba.sh bazlaat.sh
rozi>
visszakaptam a shell promtját vagy mit. Nem generált semmilyen látható kimenet.
[Szerkesztve]
Azért kell 2 szóköz, mert cut-nak akarjuk megmondani, hogy szóköz legyen a delimiter (ezt a backslash megvédi a shell elõl). A második szóköz pedig a cut argumentumait választja el.
Felraktam az én verziómat a webre: [link].
Jester
ígymá értem
Ha jól láttam ez u.a. mint amit felraktál, még az eredménye is ugyanaz. Nem produkál látható kimenetet a fájl visszaadja a promtot.
Akkor ott valami huncutság van, szerintem bele sem megy a ciklusba.
Irasd ki k értékét a ciklus elõtt.
Jester
eredménye:
rozi> chmod +x ali_g.sh
rozi> ./ali_g.sh bazlaat.sh
rozi>
rozi>
gyanúsan nem lép bele a ciklusba
ps: így néz ki a kód ott:
k=`wc -l ''$1'' | cut -d\ -f1`
x=1
echo $k
for ((i=1;i<=k;i++))
do...
[Szerkesztve]
Átmenetileg szedd ki a cut-os részt és úgy is nézd meg a k értékét.
Vagy egyszerûen próbáld ki parancssorból wc -l bazlaat.sh illetve wc -l bazlaat.sh | cut -d\ -f1 mit ad.
Jester
rozi> wc -l bazlaat.sh | cut -d\ -f1
rozi>
Ez az eredménye. Amúgy a bazlaat.sh 900 byteos kb.
rozi> wc -l bazlaat.sh
66 bazlaat.sh
rozi>
[Szerkesztve]
és ha cut<szóköz><idézõjel>-d<szóköz><idézõjel><szóköz>-f1 -et írsz?
Jester
rozi> wc -l bazlaat.sh | cut ''-d '' -f1
rozi>
Vaj miért vágja le a számot is?
[Szerkesztve]
uf, ezen kívül van még 1 probléma:
átírtam a k értékét 66-ra, hogy lássam műxik e maga az algoritmus. Íme az eredmény egy részlete (ugyanis végtelen lett vhogy a ciklus):
rozi> ./ali_g.sh bazlaat.sh
66
usage: tail [+/-[n][lbc][f]] [file]
tail [+/-[n][l][r|f]] [file]
usage: tail [+/-[n][lbc][f]] [file]
tail [+/-[n][l][r|f]] [file]
usage: tail [+/-[n][lbc][f]] [file]
tail [+/-[n][l][r|f]] [file]
.......CTRL+C-ig csinálta, ment volna világgá
Szerintem valami érdekes verzió van fent a cut és tail parancsokból ami nem támogatja a kapcsolókat amiket használnál.
Jester
uh hogy a fene enné meg és a fene fenét enne....
Nekem nincs jobb 5letem. Amit még 2 v 3 napja írtál a sima read-es, az meg nehéznek néz ki. Nem hiszem h van arra időm h kihámozzam, de ha nem találok semmit, akkor nekifogok úgy. Bár egyedül kétlem h menne.
Egy kívánságom van: tudjak eccer linuxul.
Kérlek szépen a sima read-es változat az ennyi:
i=0
exec 3<&0
cat ''$1'' | while read line
do
echo ''$line''
if [ $((i++)) -eq 24 ]
then
read <&3
i=0
fi
done
A trükk amit említettem az exec-es sor. A fájlleíróknak linuxban számuk van. A 0,1,2 rendre az stdin, stdout és stderr. A többit arra használod amire akarod. A 3<&0 átirányítás azt jelenti, hogy a 0-ás bemeneti fájlleírót (ami ezek alapján akkor az stdin) duplikálja 3-as számúként.
A while ciklus a pipe miatt alshellben fog futni, aminek az stdin-je a cat stdout-jára van kötve ezért ''elveszik'' a szülõ shell stdin-je (a terminál). Viszont a 3-as számmal ez továbbra is elérhetõ. Vagyis a belsõ read-nek megmondjuk, hogy innen olvasson. (az az átirányítás technikailag azt jelenti, hogy a 3-ast ismét visszaduplikálja a 0-ásra, mivel a read onnan fog olvasni.)
Bonyolultan hangzik, de egyszerû. Remélem érthetõ voltam
Jester
~értlek...vagy legalább is most azt hiszem. Ki is próbálom, de rosszul érzem magam a miatt, hogy ehhez semmi közöm. Bár a tárgy nem számít szinte sehova (azon kívül, hogy kötelező) és senkit se érdekel.
TéHáX!
Tökéletesen működik! köszönöm szépen! (bár még mindig zavar, hogy nem magam csináltam. Asszem ezt az exec dolgot én sose tudtam volna meg.)
Nem szokásom komplett megcsinálni mások helyett a feladatot, de te tulajdonképpen megcsináltad, csak azon a gépen nem megy.
Jester
Oh, köszi szépen. Mostmár jobb a lelkiismeretem de komolyan.
re, h úgy mondjam.
El lett fogadva a scriptem. Viszont most újra kell scriptet írjak. Ezt most saját használatra.
A lényeg, hogy ki kell keressek egy mappát. A névben szerepelnie kell a kroc szónak.
Eddig ezem van:
#! /bin/bash
for a in $1/kroc*
do
echo $a
done
Ez sajna nem megy bele az almappákba rekurzívan. Ezt hogy tudom beletenni?
[Szerkesztve]
Ha saját használatra kell, akkor feltételezem nem szükséges shell scriptben implementálni. Egyszerűen find . -type d -name '*kroc*'
Jester
igen, elég a parancs is.
ki is próbálom
ps:
eredmény:
rozi> find . -type d -name '*kroc*'
find: cannot read dir ./aset: Permission denied
find: cannot read dir ./local/etc/amanda: Permission denied
find: cannot read dir ./local/var/openldap-ldbm: Permission denied
find: cannot read dir ./local/var/openldap-slurp: Permission denied
find: cannot read dir ./local/var/amanda: Permission denied
rozi>
ez azt jelenti, hogy nem talált ott ahol próbálta? az az 5 pedig védett és nem mehetett bele?
[Szerkesztve]