GNU/Linux >> Znalost Linux >  >> Linux

Jak mohu zacyklit výstup příkazu shellu?

Zjistil jsem, že to můžete udělat pomocí dvojitých uvozovek:

while read -r proc; do
     #do work
done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)"

Tím se uloží každý řádek do pole, nikoli každá položka.


Nikdy for smyčka přes výsledky příkazu shell, pokud jej chcete zpracovat řádek po řádku, pokud nezměníte hodnotu vnitřního oddělovače polí $IFS do \n . Je to proto, že řádky budou předmětem rozdělení slov což vede ke skutečným výsledkům, které vidíte. To znamená, pokud máte například soubor jako tento:

foo bar
hello world

Následující smyčka for

for i in $(cat file); do
    echo "$i"
done

vám dává:

foo
bar
hello
world

I když používáte IFS='\n' řádky mohou být stále předmětem rozšíření názvu souboru

Doporučuji použít while + read místo toho, protože read čte řádek po řádku.

Dále bych použil pgrep pokud hledáte pids patřící do určité binární soustavy. Protože se však python může jevit jako různé binární soubory, například python2.7 nebo python3.4 Doporučuji předat -f na pgrep což umožňuje prohledávat celý příkazový řádek spíše než jen hledat binární soubory nazvané python . Ale najde se také procesy, které byly spuštěny jako cat foo.py . Byl jsi varován! Na konci můžete upravit regulární výraz předaný na pgrep jak si přejete.

Příklad:

pgrep -f python | while read -r pid ; do
    echo "$pid"
done

nebo chcete-li také název procesu:

pgrep -af python | while read -r line ; do
    echo "$line"
done

Pokud chcete název procesu a pid v samostatných proměnných:

pgrep -af python | while read -r pid cmd ; do
    echo "pid: $pid, cmd: $cmd"
done

Vidíte, read nabízí flexibilní a stabilní způsob zpracování výstupu příkazového řádku po řádku.

Btw, pokud dáváte přednost vašemu ps .. | grep příkazového řádku přes pgrep použijte následující smyčku:

ps -ewo pid,etime,cmd | grep python | grep -v grep | grep -v sh \
  | while read -r pid etime cmd ; do
    echo "$pid $cmd $etime"
done

Všimněte si, jak jsem změnil pořadí etime a cmd . Aby bylo možné číst cmd , který může obsahovat mezery, do jedné proměnné. To funguje, protože read rozdělí řádek na proměnné, kolikrát jste zadali proměnné. Zbývající část řádku – případně včetně mezer – bude přiřazena poslední proměnné, která byla zadána v příkazovém řádku.


Při použití for smyčkách v bash rozděluje daný seznam standardně o whitespaces , lze to upravit pomocí takzvaného vnitřního separátoru polí nebo IFS ve zkratce .

IFS Interní oddělovač polí, který se používá k dělení slov po rozšíření a k rozdělení řádků na slova pomocí vestavěného příkazu read. Výchozí hodnota je "".

Pro váš příklad bychom potřebovali sdělit IFS použít new-lines jako bod zlomu.

IFS=$'\n'

for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)
do
   echo $tbl
done

Tento příklad vrací na mém počítači následující výstup.

  668 /usr/bin/python /usr/bin/ud    03:05:54
27892 python                            00:01

Linux
  1. Jak používat Linuxový příkaz grep

  2. Jak přiřadit výstup příkazu proměnné shellu?

  3. Jak procházet řádky souboru?

  1. Jak zjistit, zda je výstup příkazového nebo shellového skriptu Stdout nebo Stderr?

  2. Jak mohu zkopírovat výstup příkazu přímo do schránky?

  3. Jak připojit výstup do souboru?

  1. Jak zachytit výstup top příkazu do souboru v linuxu?

  2. Jak používat příkaz su přes adb shell?

  3. Jak najdu svou verzi shellu pomocí příkazu Linux?