Использование процесса замены Bash с циклом tee и while
Я хочу использовать вложенные процессы с тройником в цикле while.
while read line; do
#process line
echo "--$line"
done < <(cat sample.file | tee >(grep "SPECLINE") | grep "LINESTOPROCESS")
Поэтому мне нужно:
- все строки в sample.file, которые содержат выражение "LINETOPROCESS", должны быть переданы в цикл, и они будут напечатаны с префиксом "-".
- все строки, содержащие "SPECLINE", должны быть напечатаны при первой замене процесса (в grep).
Я хочу не повторять образец. Файл более одного раза, так как он слишком большой и тяжелый.
С простым файлом sample.test:
line1 SPECLINE
line2 LINETOPROCESS
line3 LINETOPROCESS
line4 SPECLINE
line5 I don't need it
line6 also not
line7 also not
line8 SPECLINE
line9 LINETOPROCESS
Мой результат:
# ./test.sh
#
Мой желаемый результат:
# ./test.sh
line1 SPECLINE
--line2 LINETOPROCESS
--line3 LINETOPROCESS
line4 SPECLINE
line8 SPECLINE
--line9 LINETOPROCESS
Или я также могу принять это как вывод:
# ./test.sh
--line2 LINETOPROCESS
--line3 LINETOPROCESS
--line9 LINETOPROCESS
line1 SPECLINE
line4 SPECLINE
line8 SPECLINE
Update1
greps только для демонстрации. Мне действительно нужны эти 2 замены.
- sample.file - это http-файл.
- grep "SPECLINE" будет "hxselect -i -s ';' -c 'div.hour'
- grep "LINESTOPROCESS" будет "hxselect -i -s ';' -c 'div.otherclass' | hxpipe
hx-программы не ориентированы на строки Они читают из стандартного ввода и выводят в стандартный вывод.
Поэтому первая команда тройника выберет div с классом 'hour' и отделит их с помощью ';'. После этого труба после тройника выберет все div с классом 'otherclass', а hxpipe сгладит его для цикла для дальнейшей обработки.
3 ответа
Я бы не использовал процесс подстановки вообще.
while IFS= read -r line; do
if [[ $line = *SPECLINE* ]]; then
printf '%s\n' "$line"
elif [[ $line = *LINETOPROCESS* ]]; then
printf '--%s\n' "$line"
fi
done < sample.txt
Вы уже оплачиваете стоимость чтения входного потока построчно в bash
; нет причин добавлять накладные расходы двух отдельных grep
процессы к нему.
Один awk
процесс будет еще лучше, так как он более эффективен, чем bash
Чтение по одному символу за раз для чтения строк текста.
awk '/SPECLINE/ {print} /LINETOPROCESS/ {print "--"$0}' sample.txt
(что слишком просто, если одна строка может соответствовать обоим SPECLINE
а также LINETOPROCESS
, но я оставляю это как упражнение для читателя, чтобы исправить.)
Следующее просто перебирает весь файл и просто печатает соответствующие строки. Все остальные строки игнорируются.
while read line; do
case "$line" in
*SPECLINE*) echo "$line" ;;
*LINETOPROCESS*) echo "--$line" ;;
esac
done < sample.file
Когда вы хотите tee
Вы можете сделать 2 изменения.
Ваш тестовый код выдает LINES TOPROCESS, входной сигнал - LINETO.
Подстановка выходного процесса приводит к таким проблемам, как /questions/24865907/trojnik-s-neponimaniem-protsessa-zamenyi/24865912#24865912. Вы можете сделать это по-другому.
while IFS= read -r line; do
#process line
echo "--$line"
done < x2 |
tee >(grep "SPECLINE") >(grep "LINETOPROCESS") >/dev/null
Я не знаю hxselect
, но, похоже, он работает с полным правильно сформированным документом XML, поэтому избегайте grep
,