Мне нужен сценарий bash, который принимает вывод команды оболочки и анализирует этот вывод, чтобы извлечь идентификатор и URL-адрес веб-сайта для каждой строки в таблице, которые затем можно использовать для выполнения дополнительных команд bash.
Вот пример вывода команды.
+----+-------------------------------+----------------------------------------+---------+
| id | name | url | version |
+----+-------------------------------+----------------------------------------+---------+
| 25 | example.com | http://www.example.com/ | 3.8 |
| 34 | anotherexample.com | https://anotherexample.com/ | 3.2 |
| 62 | yetanotherexample.com | https://yetanotherexample.com/ | 3.9 |
+----+-------------------------------+----------------------------------------+---------+
Псевдокод для сценария будет примерно таким:
$output = `command --list'
for each row in $output {
$siteid=extracted_id
$url=extracted_url
$process_result = 'new_command $siteid'
log "$siteid, $url, $process_result" > log.txt
endif
Обратите внимание, что числовой идентификатор может содержать более двух цифр.
Может ли кто-нибудь дать мне отправную точку о том, как анализировать каждую строку исходной команды вывода и извлекать идентификатор и URL-адрес в качестве переменных, игнорируя первые 3 строки и последнюю строку, которые являются границей и заголовком таблицы?
Я могу разобраться в остальном, это просто анализ каждой строки, на которой я застрял.
Будем очень признательны за любые предложения / советы.
Заранее спасибо.
Большое спасибо @bioinfornatics и @jeff Schaller - я очень признателен за уровень детализации, который вы предоставили каждому.
Я использовал оба ваших ответа для своего решения, показанного ниже, где list_command генерирует вывод таблицы, а process_command запускается для каждого идентификатора веб-сайта. Я протестировал его, и он работает отлично - мне просто нужно добавить запись, и все готово.
Спасибо большое вам обоим!
#!/usr/bin/env bash
parse_result(){
local id
local name
local url
local version
while read line; do
# pull the id, name and url as variables starting from 4th line and ignoring lines starting with +---
awk -F'|' ' NR > 3 && !/^+--/ { print $2, $3, $4, $5 } ' | while read id name url version
do
RESULT="$(process_command $id)"
echo "result: $RESULT";
echo "id: $id | name: $name | url: $url | version: $version";
done
done
}
parse_result < <(list_command)
Добро пожаловать Фил Коксон,
Способ 1
Этот чистый сценарий bash, кажется, соответствует вашим потребностям
#!/usr/bin/env bash
declare id
declare name
declare url
declare version
while read line; do
if [[ ! ${line} =~ ^[\+\| ]]; then
if [[ ${line} =~ \|[[:space:]]*([[:digit:]]+)[[:space:]]*\|[[:space:]]+([[:alnum:]\.]+)[[:space:]]+\|[[:space:]]+(https?:\/\/(www\.)?[[:alnum:]]+\.[[:alpha:]]+\/?)[[:space:]]*\|[[:space:]]*([[:digit:]](\.[[:digit:]])?)[[:space:]]*\| ]]; then
id="${BASH_REMATCH[1]}"
name="${BASH_REMATCH[2]}"
url="${BASH_REMATCH[3]}"
version="${BASH_REMATCH[5]}"
echo "${id}:${name}:${url}:${version}"
fi
fi
done
Способ 2
Вы также можете создать функцию bash и использовать ее в своем скрипте следующим образом
#!/usr/bin/env bash
parse_result(){
local id
local name
local url
local version
while read line; do
if [[ ! ${line} =~ ^[\+\| ]]; then
if [[ ${line} =~ \|[[:space:]]*([[:digit:]]+)[[:space:]]*\|[[:space:]]+([[:alnum:]\.]+)[[:space:]]+\|[[:space:]]+(https?:\/\/(www\.)?[[:alnum:]]+\.[[:alpha:]]+\/?)[[:space:]]*\|[[:space:]]*([[:digit:]](\.[[:digit:]])?)[[:space:]]*\| ]]; then
id="${BASH_REMATCH[1]}"
name="${BASH_REMATCH[2]}"
url="${BASH_REMATCH[3]}"
version="${BASH_REMATCH[5]}"
echo "${id}:${name}:${url}:${version}"
fi
fi
done
}
parse_result < <(cat cmd.out)
Здесь я использую замена процесса но вы можете использовать трубу
Результат и обсуждение
Например, cmd.out - это вывод команды для анализа. В вашем случае вам необходимо заменить cat cmd.out
по твоей команде
результат 1:
$ cat cmd.out | ./app.bash
25:example.com:http://www.example.com/:3.8
34:anotherexample.com:https://anotherexample.com/:3.2
62:yetanotherexample.com:https://yetanotherexample.com/:3.9
результат 2:
$ bash app2.bash
25:example.com:http://www.example.com/:3.8
34:anotherexample.com:https://anotherexample.com/:3.2
62:yetanotherexample.com:https://yetanotherexample.com/:3.9
Хотя вы можете тщательно анализировать текст с помощью bash, иногда проще полагаться на специальный инструмент для обработки текста, такой как awk:
awk -F'|' ' NR > 3 && !/^+--/ { print $2, $3, $4} ' > log.txt
Это указывает awk разбивать строки на поля на основе разделителя |
; программный код внутри одинарных кавычек разбивается как:
NR > 3 &&
- если количество обработанных записей (строк) больше 3 и ...!/^+--/
- ... и если линия не начать с +--
print
поля 2, 3 и 4... все в конечном итоге были перенаправлены на log.txt
файл.