Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Karlitos 14. 03. 2015, 17:44:35
-
Zdravím,
snažím se teď proniknout do kódování v bashi a mám trocho problém s chápáním některých věcí které bude asi nejlepší vysvětilit na příkladech.
Při poznávání jak funguje cut jsem si zkoušel upravit výstup příkazu ps. Narazil jsem na problém, že cut -d " " bude dělit řádky po mezerách, ale to nefungovalo jak mělo pro libovonlý počet mezer. Hledal jsem jak pro parametr -d zadat libovolný počet mezer, ale cut očekává jeden character.
Nakonec jsem našel řešení přez tr -s " ", což v řetězci nahradí libovolné množství mezer za jednu jedinou a tak příkaz
ps -aux | tr -s ' '
vyhodí seznam procesů kde jsou v řádcích sloupečky oddělené jen jednou mezerou.
Pak jsem se to snažil dát do skriptu a narazil na tyhle věci:
PROC=`ps -aux`
echo $PROC
vypíše výstup z ps bez zalamování do jednoho řádku. Aby se mi výtup zalomil musím použít
PROC=`ps -aux`
echo "${PROC}"
Což funguje ale zatím jsem nepřišel na to proč tomu tak ja/musí být.
No ale jak teď udělat to odstranění vícečetných mezer ?
echo $(echo $PROC | tr -s ' ')
mi všechno vypíše do jednoho řádku.
Ve výsledku bych se moc rád dobral stejného výstupu jako když v terminálu zadám
ps -aux | tr -s ' ' | cut -d " " -f1,2,3,4
Vím že na ostranění vícečetných mezer lze použít awk/sed ale já bych hlavně moc rád pochopil jak to s tím víceřádkovým výpisem je a kde dělám co blbě.
Diky!
-
moc nechapu proc si to komplikujes tou dalsi zavorkou
PROC=`ps -aux`
echo "${PROC}" | tr -s ' ' | cut -d " " -f1,2,3,4
-
Nepochopil jsem úplně co je cílem, ale pokusím se pomoct.
Proč prostě neduěláš:
PROC=`ps -aux | tr -s ' ' | cut -d " " -f1,2,3,4`
echo "$PROC"
nebo ještě lépe:
PROC=`ps -axo user,pid,%cpu,%mem | tr -s ' '`
echo "$PROC"
(ale to by bylo pro učení se moc jednoduché ;) )
Vysvětlení některých zmíněných jevů:
PROMENNA=`prikaz_jehoz_vystup_obsahuje_newliny_a_mezery`
...do proměnné se uloží výstup tak jak je
echo "$PROMENNA"
...vypíše obsah proměnné tak jak je
echo "${PROMENNA}"
...to samé, je to užitečné jen ve chvíli kdy chceme třeba vypsat "${PROMENNA}neco navic" nebo používat substituce
echo $PROMENNA
...$PROMENNA se rozvine do více parametrů příkazu echo. Je to jako kdybys napsal třeba
echo ahoj cau \
nazdar tepic
tak příkaz echo vidí že má 4 parametry a vypíše je za sebe oddělené mezerami. čímž nastane to, že se vždy za sebou jdoucí sada libovolných bílých znaků (vč newline) přemění na jednu mezeru
echo `prikaz` $(prikaz) "$(prikaz)"
rozdíl mezi `...` $(...) je velice malý (za úkol si ho zjisti), já raději používám to druhé kvůli čitelnosti. (Ne)uzavření výrazu do uvozovek má stejný následek jako u proměnné.
...už je alespoň něco jasné ? :)
-
Díky! Cílem je pochopit jak funguje skriptování v bashi a prohloubit znalosti. Já sem začínal na Javě a docela dobře dávám Python, ale u bashe stále dost bojuju se syntaxí a podobně.
Vidím že chyba byla v těch uvozovkách a moc děkuju za vysvětlení. Po třetím přečtení mi to konečne docvaklo celé :-D
Budu s tím teď zase trochu dál hrát a uvidíme kam se dostanu.
-
libcha: dobre skolitel ;) a to stacilo napsat, protoze zavrene do "" to zustane jako jeden parameter :) tak aspon dodam:
- informace o tom ze echo parametry oddeluje automaticky mezerou je v: help echo (help prikaz - jde o napovedu internich prikazu bash), nebo man echo pri pouziti samostatneho echo prikazu
- pokud script ma v hlavicce #!/bin/bash pouzije se interni echo bashe, to funguje jak je receno
- pokud script a v hlavicce #!/bin/sh pouzije se samostatnej echo prikaz(sh interni nema), ten vyzaduje pro stejne chovani parametr -e (protoze narozdil od interniho echo prikazu bashe to nema jako defaultni chovani(aby newline representoval jako novyradek))
- i pri pouziti bash lze vynutit ve scriptu pouziti samostatneho echo napr:
ECHO=$(which echo)
$ECHO "text"
-
Hledej "Vilém Vychodil: Příručka českého uživatele".
-
Děkuju ještě jednou všem za vysvětlení. Narazil jsem ale na jednu nejasnost:
Očekával jsem ,že následující příkaz bude správný podle vzoru "$(prikaz)":
echo "$($PROC | tr -s ' ')"
Jenže to tr -s ' ' se neprovede.
Když odstraním závorky tak to funguje:
echo $PROC | tr -s ' '
s tím ale, že echo interpretuje to co je napravo zase jako vícečetný vstup.
Když celý příkaz zavřu mezi uvozovky tak dostanu víceřádkový výstup, ale bez odstranění vícečetných mezer
echo "$PROC | tr -s ' '"
No a správně funguje
echo "$PROC" | tr -s ' '
Mě to mate. Očekával bych že se tento příkaz bude interpretovat jako: interpretuj hodnotu proměnné PROC, udělej z ní řetězec a pošli to na vstup tr, kde se odstraní vícečetné mezery a toto bude vstupem echo, které to bude považovat za vícečetný vstup
Proto jsem čekal že by měla fungovat verze "$(prikaz)" což se ovčem neděje.
-
V prvním příkazu voláš něco uložené v $PROC a předáváš to pajpou do tr. Zřejmě jsi zapomněl jedno echo:
echo "$(echo $PROC | tr -s ' ')"
(pozor na to že $proc uvitř tu stále není v uvozovkách...
V druhém příkazu asi chápeš co se děje - je to obsah uvnitř $(...) v mnou opraveném prvním příkazu.
Třetím příkaz vypíše to samé co echo "$PROC"
jen se na konci výstupu objeví | tr -s ' '
Je to proto, že se echuje to co je uzavřené v uvozovkách - zde tedy i symboj pajpy, jméno příkazu tr a jeho "parametry".
Čtvrtý příkaz už asi zas chápeš.
-
Aha díky moc :)
Odpovědi vedou bohužel k dalším otázkám. Ale mám pocit, že už začínám nacházet i vlastní odpovědi.
Mátlo mě proč bylo potřeba dát to chybějící druhé echo do příkazu
echo "$(echo $PROC | tr -s ' ')"
když to přeci fungovalo i stylem
echo "$PROC" | tr -s ' '
Pak mě ale došlo že jsem ten druhý příkaz nejspíš interpretoval chybně, tedy:
Udělej výstup do terminálu (echo) z: hodnoty proměnné PROC poslané skrz pipe na tr -s ' ' Tedy jako kdyby tam byla za echo závorka určijící pořadí vykonávání echo ($PROC | tr -s ' ')
Jenže takto asi pipe perátor nefunguje, předpokládám že nemůže dostat hodnotu promněnné pomocí $PROMENNA ale musí dostat výstup nějakého příkazu tedy echo $PROMENNA
Správná interpretace toho druhého příkazu by tedy asi měla být:
Udělej výstup do terminálu (echo) z hodnoty proměnné PROC a celý výstup pošli skrz pipe na tr -s ' ' který předpokládám dělá standartně výstup do stdout a proto se to vypíše. A proto když to celé ještě uzavřu do $( ... ) tak si to můžu uložit do další promněnné.
Asi to říkám blbě ale začíná se mi to pomalu jasnit. Tedy doufám ;)
-
...
předpokládám že nemůže dostat hodnotu promněnné pomocí $PROMENNA ale musí dostat výstup nějakého příkazu tedy echo $PROMENNA
...
promenou tim ziskas ale pouzije se jako prikaz, viz to me nastaveni externiho prikazu echo do promene ECHO (http://forum.root.cz/index.php?topic=10868.msg124594#msg124594)...
pokud ji chces zobrazit, spravne uz ti doslo ze prikazem na zobrazeni :)
dalsi tema k zamysleni je ze s promenou se daji delat veci o kterejch se ti jeste nestni ;)
napr. kdyz budes chtit zmenit obsah nejake promene, muzes to udelat takto:
echo "Nova hodnota je: $(echo $stara | sed 's/neco/zaneco/g')"
jenomze, pokud se podivas sem (http://tldp.org/LDP/abs/html/parameter-substitution.html) nebo sem (http://wiki.bash-hackers.org/syntax/pe) zjistis ze totozne docilis timto:
echo "Nova hodnota je: ${stara//neco/zaneco}"
:)