Подсчет списка строк в каждой строке нескольких файлов

С zshэто должно быть просто вопросом:

precmd() print -z 'foo '

Или, чтобы избежать переопределения команд, поставленных в очередь пользователем, с помощью Alt+q:

zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init

С помощью bashвместо xdotoolвы можете использоватьTIOCSTIioctl:

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'

Это предпочтительнее xdotool, поскольку он вставляет эти символы непосредственно во входной буфер устройства bash, с которого считывается. xdotoolбудет работать только в том случае, если запущен X-сервер (не будет работать на консоли или реальных терминалах или надssh(без -X), например ), который идентифицируется как $DISPLAYи это тот, с которым вы взаимодействуете, и который работает эмулятор терминала bash, имеет фокус при оценке $PROMPT_COMMAND.

Теперь, как и в вашем случае xdotool, поскольку ioctl()выполняется до отображения подсказки, а дисциплина линии терминала tty выводится из режима icanon+echoс помощью readline, вы, вероятно, увидите эхо того fooиз-за дисциплины линии tty, которая портит отображение.

Вы можете обойти это, вместо этого вставив строку, чье эхо невидимо (, например U+200B, если используются исключительно локали Unicode ), и привязать ее к действию, которое вставляет"foo ":

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"

Или вы можете задержать TIOCSTIioctl на время, достаточное для инициализации readline:

insert_with_delay() {
  perl -le 'require "sys/ioctl.ph";
            $delay = shift @ARGV;
            unless(fork) {
              select undef, undef, undef, $delay;
              ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
            }' -- "$@";
}
PROMPT_COMMAND='insert_with_delay 0.05 "foo "'

Если, как и в подходах zsh, вы хотите обработать случай, когда пользователь вводит текст до отображения подсказки,вы можете либо

  • слить , что при выполнении tcflush(0, TCIFLUSH)в perlперед TIOCSTIioctl (также требуется опция -MPOSIX)или
  • Как и в подходе zsh, убедитесь, что fooвставлен в начале буфера, вставив^A(при условии, что вы используетеemacs(режим редактирования по умолчанию ), в котором курсор перемещается в начало строки )до fooи ^Eпосле (для перехода к концу):

    insert_with_delay 0.05 $'\1foo \5'
    

    или

    bind $'"\u200b":"\1foo \5"'
    
0
03.12.2019, 21:14
2 ответа

Если

$ cat strings
journal
moon pig
owls

и

$ cat file
I like to journal about owls and moon pigs.
owls are birds. moon pigs are not.
owls owls owls

тогда вы можете использовать GNU awk следующим образом

gawk '
    NR == FNR { string[++n] = $0; next}
    {
        for (i=1; i<=n; i++)
            # gsub() return the number of replacements.
            # it is a convenient way to count instances of fixed strings.
            count[i][FNR] = gsub(string[i], string[i])
        if (FNR > max)
            max = FNR
    }
    END {
        for (i=1; i<=n; i++) {
            for (j=1; j<=max; j++)
                printf "%s\t", 0 + count[i][j]
            print ""
        }
    }
' strings file

выходы

1   0   0
1   1   0
1   1   3

Я вообще не объяснял эту awk-программу. Посмотрите, сможете ли вы понять это, и задайте любые вопросы, которые у вас есть.

2
28.01.2020, 02:29

Основной алгоритм для получения массива счетчиков для каждой строки, который немедленно обрабатывает каждую строку,:

gawk ' NR == FNR { string[++n] = $0; next}
       { for (i=1; i<=n; i++) 
             printf("%s\t", gsub(string[i],""))
         print ""
       }
     ' strings file

Это основано на gsub для подсчета выполненных замен.

Это приведет к выводу:

1   1   0   
0   0   2

Это просто транспонированная матрица того, что вы просили. В awk становится немного сложнее транспонировать столбцы и строки. А также обрабатывать более одного файла. Мы можем объединить (конвейер )оба скрипта, используя пустую строку как индикатор изменения файла. Двойная обработка одного и того же файла:

awk '
    NR == FNR { string[++n] = $0; next}
    FNR==1 && p == 1 { print "" }
    { for (i=1; i<=n; i++) printf("%s\t", gsub(string[i],""))
      print ""
      p = 1
    }
    END    { print "" }
' strings.txt    infile.txt    infile.txt |
awk '!/^$/{ 
       for(i=1;i<=NF;i++) f[NR-r][i]=$i ;
       if (maxf<NF) maxf = NF ;
       if (maxr<(NR-r)) maxr = NR-r ;
     } 
     /^$/{
         for(      i=1 ; i<=maxf ; i++ )
         {
             for(  j=1 ; j<=maxr ; j++ )
                 printf("%s\t",f[j][i])
             print ( "loop", maxf, maxr, r )
         }
     r=NR
     print ( "" )
     maxf=0
     maxr=0
     delete f
     }'

Что дает ответ на вопрос:

1   0
1   0
0   2

1   0
1   0
0   2
0
28.01.2020, 02:29

Теги

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