Bash, víceřádkový výstup a odstranění mezer

Karlitos

Bash, víceřádkový výstup a odstranění mezer
« kdy: 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
Kód: [Vybrat]
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:
Kód: [Vybrat]
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
Kód: [Vybrat]
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 ?
Kód: [Vybrat]
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
Kód: [Vybrat]
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!


#

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #1 kdy: 14. 03. 2015, 18:36:08 »
moc nechapu proc si to komplikujes tou dalsi zavorkou

Kód: [Vybrat]
PROC=`ps -aux`
echo "${PROC}" | tr -s ' ' | cut -d " " -f1,2,3,4

libcha

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #2 kdy: 14. 03. 2015, 18:45:09 »
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é ? :)

Karlitos

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #3 kdy: 14. 03. 2015, 19:00:03 »
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.

nobody

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #4 kdy: 14. 03. 2015, 19:08:05 »
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"


karel

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #5 kdy: 14. 03. 2015, 19:14:33 »
Hledej "Vilém Vychodil: Příručka českého uživatele".

Karlitos

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #6 kdy: 15. 03. 2015, 10:23:13 »
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)":
Kód: [Vybrat]
echo "$($PROC | tr -s ' ')"Jenže to tr -s ' ' se neprovede.

Když odstraním závorky tak to funguje:
Kód: [Vybrat]
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
Kód: [Vybrat]
echo "$PROC | tr -s ' '"
No a správně funguje
Kód: [Vybrat]
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.

libcha

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #7 kdy: 15. 03. 2015, 10:55:30 »
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:
Kód: [Vybrat]
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
Kód: [Vybrat]
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š.

Karlitos

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #8 kdy: 15. 03. 2015, 13:26:39 »
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
Kód: [Vybrat]
echo "$(echo $PROC | tr -s ' ')"když to přeci fungovalo i stylem
Kód: [Vybrat]
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  ;)

nobody

Re:Bash, víceřádkový výstup a odstranění mezer
« Odpověď #9 kdy: 15. 03. 2015, 14:33:11 »
...
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...
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 nebo sem zjistis ze totozne docilis timto:
echo "Nova hodnota je: ${stara//neco/zaneco}"
:)