Замена процесса с мишенью и вставкой

Хорошо, таким образом, ответ: по некоторым причинам, во время конфигурации, все элементы UI были на самом деле дублированы. Удаление дубликатов с dconf-редактором, кажется, фиксирует его. Благодаря don_crissti для указания на меня в правильном направлении!

6
11.06.2014, 02:51
3 ответа

Причина, по которой виден вывод исходной команды, заключается в том, что tee выводит на stdout, а также на указанные файлы. Чтобы отбросить это, вы можете поставить >/dev/null в конец команды или перенаправить этот вывод на одну из ваших подстановок процесса, добавив дополнительную >, например:

command | tee >(sed -rn 's/.*foo (bar).*/1/p') > >(awk '{print $3}')

или проще просто использовать другой канал:

command | tee >(sed -rn 's/.*foo (bar).*/1/p') | awk '{print $3}'

Что касается объединения результата двух подстановок процесса, используя paste, если только нет какого-то непонятного трюка с оболочкой, о котором я не знаю, нет способа сделать это без использования именованного канала. В конечном счете, это две строки (отформатированные для большей ясности):

mkfifo /tmp/myfifo
command |
  tee >(sed -rn 's/.*foo (bar).*/1/p' >/tmp/myfifo) |
  awk '{print $3}' |
  paste /tmp/myfifo -

Если вы помещаете это в скрипт, также рассмотрите возможность использования рекомендаций по созданию временного именованного канала здесь.

9
27.01.2020, 20:23

Все это можно сделать только в sed.

command | 
sed '/\([^ ][^ ]*  *\)\{2\}/{h
         s///;s/^  *//;s/ .*/p
     g};s/.*foo \(bar\).*/\1/p;d'  

Но что касается другого, у вас есть тройник около файлов |pipe:

cmd1 | {     
    {   tee /dev/fd/3 | 
        cmd2 >&2
    } 3>&1 | 
    cmd3
} 2>&1 |paste

Но так как вы уже используете sed, вы можете использовать его как smart tee и дублировать/переадресовывать только тогда, когда вам это необходимо:

cmd | { 
    sed -n 'p;s/.*foo \(bar\).*/\1/w /dev/fd/3' |
    awk ...
} 2>&1
3
27.01.2020, 20:23

ИМХО более изящно (ясно понятно )избегая "трюков" с tee.
@mikeserv уже показал команду sed, вы также можете «вставить» внутрь awk.
Пример с заменой команды командой printf:

$ printf "foo %s %s %s\n"  {1..30} 
foo 1 2 3
foo 4 5 6
foo 7 8 9
foo 10 11 12
foo 13 14 15
foo 16 17 18
foo 19 20 21
foo 22 23 24
foo 25 26 27
foo 28 29 30

Требование (пример):
Вставить вывод из

  1. sed -rn '/3/ s/[^ ]* ([^ ]*).*/\1/'
    Выберите только строки с «3» и получите второе поле.
    Это строки с первым номером 1, 13, 22 и 28
  2. awk 'NR>2 {print $3}'
    Показать третье поле для всех строк

Поток из требования 1 захватывается в массив bar,
поток из требования 2 захватывается в массив secondstream.
После обработки всех входных данных в блок END вставляются захваченные потоки.

printf "foo %s %s %s\n"  {1..30} |
   awk '/3/  {bar[barcounter++]=$2}
        NF>2 {secondstream[streamnr++]=$3} 
        END  {for (i=0;i<streamnr;i++) print bar[i], secondstream[i];}
       '

Результат:

1 2
13 5
22 8
28 11
 14
 17
 20
 23
 26
 29
0
27.01.2020, 20:23

Теги

Похожие вопросы