Як призначити вихід команди в масив?


79

Мені потрібно призначити результати з grepмасиву ... наприклад

grep -n "search term" file.txt | sed 's/:.*//'

В результаті з’явилася купа рядків із номерами рядків, у яких був знайдений пошуковий термін.

1
3
12
19

Який найпростіший спосіб призначити їх масиву bash? Якщо я просто присвоюю їм змінну, вони стають рядком, розділеним пробілом.


Подивіться це питання
beerbajay

рядки, відокремлені пробілом, легко проходять в bash.
Шиплу Мокаддім

о-о-о ... слід було б провести більш ретельний пошук. Дякую.
стельовий кіт

Окрім того, це загальноприйняте використання шаблонів, grepщоб отримати номери рядків чогось і врешті-решт передати їх інструменту, який має власну підтримку регулярних виразів. Тоді він може знайти ті самі рядки, що і grepзнайдені, без об’їзду і з’ясування номерів рядків сірників.
триплі

Відповіді:


137

Щоб призначити вивід команди масиву, потрібно використовувати заміну команди всередині присвоєння масиву. Для загальної команди commandце виглядає так:

arr=( $(command) )

У прикладі OP це звучало б так:

arr=($(grep -n "search term" file.txt | sed 's/:.*//'))

Внутрішній $()запускає команду, тоді як зовнішній ()викликає вихід як масив. Проблема цього полягає в тому, що він не буде працювати, коли вихідні дані команди містять пробіли. Щоб вирішити це, ви можете встановити IFSна \n.

IFS=$'\n'
arr=($(grep -n "search term" file.txt | sed 's/:.*//'))
unset IFS

Ви також можете вирішити потребу в sed, виконавши розширення кожного елемента масиву:

arr=($(grep -n "search term" file.txt))
arr=("${arr[@]%%:*}")

4
плюс один для обробки справи з пробілами в елементах. Саме те, що я шукав.
Владиславс Довгалець,

1
IFS речі чудові! Шукав годинами!
magnusarinell

для мене це працювало лише без зовнішніх дужок dvmList=`grep -RohP '(?<=oramds:).+\.dvm' myFolder'
tuxErrante

@bastaPasta Це не є призначенням масиву. Призначення масиву може не спрацювати для вас, якщо ви не використовували оболонку, яка підтримувала масиви.
jordanm

Ви маєте рацію, що я використовував sh замість bash, але це чудово працює у
циклі

10

Рядки, розділені космосом, легко проходять в bash.

# save the ouput
output=$(grep -n "search term" file.txt | sed 's/:.*//')

# iterating by for.
for x in $output; do echo $x; done;

# awk
echo $output | awk '{for(i=1;i<=NF;i++) print $i;}'

# convert to an array
ar=($output)
echo ${ar[3]} # echos 4th element

якщо ви думаєте про простір у використанні імені файлу find . -printf "\"%p\"\n"


5
Але не працює для файлів із пробілами.
jordanm

@jordanm usefind . -printf "\"%p\"\n"
Шиплу Мокаддім

@ShipluMokaddim, це не працює. for x in $outputза допомогою такої findкоманди файл з іменем two wordsбуде повторюватися як одне значення, так "twoі інше значення words".
Чарльз Даффі,

@ShipluMokaddim, ... те ж саме вірно, якщо ви використовуєте ar=( $output )з outputпризначеним таким чином, оскільки результати розширення параметрів та заміни команд не проходять фазу синтаксичного аналізу видалення цитат.
Чарльз Даффі,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.