Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

sed regulární výrazy

Marek Stopka
Marek Stopka
4. 6. 2005 13:30

sed regulární výrazy

Dobrý den snařím se napsat příkaz, který by do proměnné přiřadil z názvu souboru "messages.1.gz a wtmp.1.gz" jen část před první tečkou dostal sem se k tomu že sem napsal regulární výraz, který identifikuje část .1.gz '\.1\.gz' ovšem nepodařilo se mi najít způsob jak bych řekl sedu(může být i jiná aplikace), aby tuto část uřízl a do proměnné uložil pouze "messages a wtmp". Pročítal sem manualové stránky regex a sed ovšem sem tam nic nenašel. Předem děkuji za každé nasměrování.
Dominik Sauer
Dominik Sauer (neregistrovaný)
4. 6. 2005 14:01 Nový

to cele nokoli v lehu.

celé vlákno
s/^(.*)\.1\.gz$/\1/g nahradi (to co je v zavorkach).1.gz (tim, co je v zavorkach).
jka
jka
4. 6. 2005 14:25 Nový

reseni sedem nebo basename

celé vlákno
snad rozumim zadani

Reseni sedem
PROMENNA=`echo jmeno.1.gz | sed s/"\(.*\)\.1\.gz"/"\1"/`

IMHO lepsi je:

PROMENNA=`basename jmeno.1.gz .1.gz`
Marek Stopka
4. 6. 2005 14:34 Nový

Re: reseni sedem nebo basename

celé vlákno
Moc ti díky řešení číslo 2 funguje, řešení číslo 1 jsem nezkoušel.
miEro
miEro (neregistrovaný)
4. 6. 2005 15:26 Nový

Re: reseni sedem nebo basename

celé vlákno
alebo este jednoduchsie pomocou
PROMENNA=jmeno.1.gz
echo ${PROMENNA%.1.gz}
Marek Stopka
4. 6. 2005 19:22 Nový

Re: reseni sedem nebo basename

celé vlákno
Tak ještě bych sem přidal jeden dotaz snad to nebude vadit nevíte proč mi toto nefunguje:
for file in *.1.gz; do
        mv $file $(echo ${file%.1.gz})
done
skoušel sem i toto:
for file in *.1.gz; do
        tmp2=$(echo ${file%.1.gz})
        mv $file $tmp2
done
ale to taky nefunguje.
Miroslav Rudišin
4. 6. 2005 22:37 Nový

Re: reseni sedem nebo basename

celé vlákno
netreba hned vsetko do pismenka prepisovat :-)) inak uvodzovky su dolezite, inak budu robit problemy subory s medzerami asi to chcete aj rozbalit, ze? preco nie rovno?
for file in *.1.gz; do
        zcat \"${file%.1.gz}\" > \"$file\"
done
inak pekne funguje aj
zcat FILE.gz | less
Kit
Kit (neregistrovaný)
5. 6. 2005 8:56 Nový

Re: reseni sedem nebo basename

celé vlákno
zcat IMHO pouze zavolá gunzip, je tedy zbytečný.
for file in *.1.gz; do
   gunzip <"$file" >"${file%.1.gz}"
done
ale tato konstrukce je zbytečně složitá, pro rozbalení více souborů stačí zadat:
gunzip *.1.gz
Kit
Kit (neregistrovaný)
5. 6. 2005 9:00 Nový

Re: reseni sedem nebo basename

celé vlákno
Ještě pěkně funguje
less FILE.gz
Pichi aura:75
6. 6. 2005 19:39 Nový

Re: reseni sedem nebo basename

celé vlákno
Vy máte na disku soubory s názvem v uvozovkách? Něco jako

$ ls \"*\"
"blbejnazev"
Kit
Kit (neregistrovaný)
5. 6. 2005 8:46 Nový

Re: reseni sedem nebo basename

celé vlákno
Je tam navíc echo, které je v tomto případě zbytečné:
for file in *.1.gz; do
    mv "$file" "${file%.1.gz}"
done
Nezapomínejte na uvozovky, jinak si koledujete...
Kit
Kit (neregistrovaný)
5. 6. 2005 9:07 Nový

Re: reseni sedem nebo basename

celé vlákno
Ještě mě napadlo jedno řešení, pokud není třeba rozbalovat, ale jen odstranit přípony:
rename ".1.gz" "" *.1.gz
Pichi aura:75
6. 6. 2005 16:28 Nový

Re: reseni sedem nebo basename

celé vlákno
No to by musel mý ten správný rename (rozuměj třeba ten co je v FC). U mě by to bylo třeba

rename 's/\.1\.gz$//' *.1.gz

(perlutils rename)
barney
barney (neregistrovaný)
4. 6. 2005 19:39 Nový

hmm zlozitejsie by to neslo ?

celé vlákno
echo messages.1.gz | sed -e 's/\.1\.gz$//'
Pichi aura:75
6. 6. 2005 16:24 Nový

Re: reseni sedem nebo basename

celé vlákno
Dělat 2x fork+exec a 2x pipe v prvním případě a jednou fork+exec a jedna pipe v druhém případě místo

PROMENNA=${PROMENNA%%.*}
nebo
PROMENNA=${PROMENNA%.1.gz}

je dnes nějaká móda?
uživatel si přál zůstat v anonymitě
4. 6. 2005 14:49 Nový

cut ?!?!

celé vlákno
jezis... nie je jednoduchsie pouzit:

echo ... | cut -d'.' -f 1
????

naco pouzivat kanon na vrabce (sed)
uživatel si přál zůstat v anonymitě
4. 6. 2005 14:51 Nový

Re: cut ?!?!

celé vlákno
ehm... sorry... to basename som si nevsimol :) mae culpa
uživatel si přál zůstat v anonymitě
4. 6. 2005 15:32 Nový

Re: cut ?!?!

celé vlákno
Toto elegantni reseni s cut, ktere neni kanon na vrabce, je typicka ukazka spatneho programovani....
Zkusim-li tomu zadat jan.novak.1.gz,
vypadne ...chvilka napeti.... "jan" misto "jan.novak", jak by melo dle zadani a (meho) zdraveho rozumu byt.
Vyse uvedene reseni se sedem funguje lepe....Osobne bych asi pouzil basename, protoze pri prvnim pohledu
na program vim, ze to urizne priponu a nemusim studovat ten strasne neprehledny regularni
vyraz pro sed (perl,...).

Jeste bych dodal ze basename oreze take cestu k souboru, tj. z "/home/jan.novak.1.gz" zbude jenom "jan.novak". (man cut, man basename)
Pichi aura:75
6. 6. 2005 16:14 Nový

Re: cut ?!?!

celé vlákno
Co to máte za basename? moje basename udělá tohle
$ basename /home/jan.novak.1.gz
jan.novak.1.gz

jinak v zadání je doslova napsáno "jen část před první tečkou"

takže na to máme ${var%%.*} které dělá přesně tohle

jinak další otázka v diskusi bylo na

for i in *.1.gz
do
mv "$i" "${i%.1.gz}"
done

P.S.: To je nějaká nová móda radit blbě a ani si to neověřit?
Pichi aura:75
6. 6. 2005 16:40 Nový

Re: cut ?!?!

celé vlákno
Nevšim jsem si, že už víše je to s basename ukázáno správně. Jinak basename je berlička pro shelly co neumí konstrukce ${var#pattern} ${var##pattern} ${var%pattern} ${var%%pattern} což je csh, kcsh, další klony csh a některé minimalistické shelly. Od těch dob, co tohle umí i sh je zbytečné spouštět podproces basename a nutit shell parsovat jeho výstup.

basename() { local a="${1##*/}"; [ -z "$2" ] && echo $a || echo ${a%$2}; }
Pichi aura:75
6. 6. 2005 17:37 Nový

Re: cut ?!?!

celé vlákno
Trochu brutálnější verze

basename() { [ -n "$2" ] && set -- "${1%$2}"; echo ${1##*/}; }

stejně se to uvnitř skriptu bude dělat prvním způsobem, protože nebudu přece dělat podproces kvůli přiřazení a=$(basename bla/bla/bla.bl) (a taky se mi nechce koukat do zdrojáku jestli to náhodou shell nějak neoptimalizuje).

Nebo si můžu udělat funkci, která rovnou přiřadí do proměné

basenameset() { [ $# -ge 2 ] && { eval $1=\"${2##*/}\"; [ -n "$3" ] && eval $1='"${'$1'%$3}"'; } }
Pichi aura:75
6. 6. 2005 18:01 Nový

Re: cut ?!?!

celé vlákno
Trošku elegantnější

basenameset() { [ -n "$3" ] && set -- $1 "${2%$3}"; [ $# -ge 2 ] && eval $1="${2##*/}"; }
Pichi aura:75
6. 6. 2005 18:05 Nový

Re: cut ?!?!

celé vlákno
V tom evalu musí být uvozovky eskejpnuty jinak to nezebere názvy s mezerou a ten první parametr musí být platné jméno proměné, takže taky žádné skopičiny.

basenameset() { [ -n "$3" ] && set -- $1 "${2%$3}"; [ $# -ge 2 ] && eval $1=\"${2##*/}\"; }
Pichi aura:75
7. 6. 2005 8:23 Nový

Re: cut ?!?!

celé vlákno
Trošku vylepšená superbrutus verze s ošetřením parametrů a bez zbytečného testu na třetí parametr.

basenameset() { set -- "$1" "${2%$3}"; case "$1" in [^a-zA-Z]*|*[^a-zA-Z0-9]*);; ?*) eval $1=\"${2##*/}\";; esac }
uživatel si přál zůstat v anonymitě
6. 6. 2005 7:48 Nový

co treba takhle

celé vlákno
no nevim... me stacilo toto

STR="messages.1.gz"

echo $STR|cut -d. -f1
Pichi aura:75
6. 6. 2005 16:19 Nový

Re: co treba takhle

celé vlákno
No hlavně že máme zbytečně moc systémových prostředků. Dvakrát fork+exec a jedna roura navíc dnes už nikoho nebolí. Jen toho nikdo nesmí chtít udělat milionkrát, že?
uživatel si přál zůstat v anonymitě
6. 6. 2005 17:31 Nový

Re: co treba takhle

celé vlákno
ehm? preco dva krat fork+exec? neni to len raz? (len na cut?)
Pichi aura:75
6. 6. 2005 17:51 Nový

Re: co treba takhle

celé vlákno
Máte pravdu. Zdá se, že to jde udělat s jedním fork+exec

schematicky:
pipe()
fork()
potomek: exec(cut)
write()
wait(potomek)

jenže vy to tam nikde nepřiřazujete do proměnné (což je požadavek v zadání) a na to se shell ještě jednou forkne na realizaci $() a tak jsou to dvakrát fork a jednou exec a jedno pipe.
uživatel si přál zůstat v anonymitě
6. 6. 2005 18:35 Nový

Re: co treba takhle

celé vlákno
hm... njn... ale stejne nechapem naco robit nieco v shelli efektivne. IMHO v shelli urobim niektore veci hlavne rychlo, raz ich pouzijem a nasledne zahodim. Ked chcem nieco spravit efektivne, tak to stejne v shelli robit nebudem, lebo tomu forkovani/execovani sa aj tak nevyhnem...
Pichi aura:75
6. 6. 2005 19:36 Nový

Re: co treba takhle

celé vlákno
Proč něco v shellu dělat efektivně? No třeba potřebuju rychle ad hoc udělat nad několika sty tisici souboru v několika set adresářích. To se pak hodí vědět, že na

find -type f -name '*.mp3' -exec rm {} \;

si počkám podstatně déle než na

find -type f -name '*.mp3' -print0 | xargs -0 rm

no a když je budu chtít přejmenovat několik tisíc souborů pomocí

for i in *.jpg; do mv "$i" "$(echo $i|sed 's/\.jpg$/\.jpeg/')"; done

je dobré vědět, že to není zrovna dobrý nápad a budu to mít mnohem dřív hotové, když napíšu

for i in *.jpg; do mv "$i" "${i%.jpg}.jpeg"; done

a vůbec nejdřív se dočkám výsledku s

find -maxdepth 1 -type f -name '*.jpg' -print0 | xargs -0 rename 's/\.jpg/.jpeg/'

(verze pro opravdu velké množství souborů v adresáři s hodně velkým množstvím souborů s jiným jménem než *.jpg, 10000 a více, jinak si vystačím bez findu)
uživatel si přál zůstat v anonymitě
6. 6. 2005 20:57 Nový

Re: co treba takhle

celé vlákno
"
je dobré vědět, že to není zrovna dobrý nápad a budu to mít mnohem dřív hotové, když napíšu

for i in *.jpg; do mv "$i" "${i%.jpg}.jpeg"; done

"


:)) to snad nemyslite vazne :D nad "nekolik tisic soubormi" vam toto stejne selze kvuli tomu "i in *.jpg" a tomu, ze sa to rozvinie na nieco priiiilis dlhe a prekroci to nejaky limit... takze bez toho findu si stejne nepomozete....
Pichi aura:75
7. 6. 2005 7:51 Nový

Re: co treba takhle

celé vlákno
Další expert co jen planě plácá a nevyzkouší si to? Tak si to zkuste! Vtip je v tom, že se to nerozvine, ale shell to udělá chytře. A příště, když nevím, tak to zkusím.
Pichi aura:75
7. 6. 2005 7:59 Nový

Re: co treba takhle

celé vlákno
$ ls
$ for((i=0;$i<10000;i++)); do touch zbytecne_dlouhej_prefix_$i; done
$ echo *
zbytecne_dlouhej_prefix_0 zbytecne_dlouhej_prefix_1 zbytecne_dlouhej_prefix_2 ... zbytecne_dlouhej_prefix_9999
$ ls *
bash: /bin/ls: Příliš dlouhý seznam argumentů
$ for i in zbytecne_dlouhej_prefix_*; do rm $i; done
$ ls
$

Školení: Linux – Firewall, Samba, VPN

Na třídenním školení se naučíte nainstalovat a spravovat Firewall a Router, SAMBA Doménový a Souborový server. Dále si zprovozníte vlastní, zabezpečený VPN server.

Podrobnější informace a přihláška