Использование процесса замены 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,

Другие вопросы по тегам