3

Какие команды Unix можно использовать для определения длины строки, в которой слово появляется в тексте? "Span" равен номеру строки последнего экземпляра слова минус номер строки первого экземпляра слова.

1| unix is on two lines
2| once above, and once below
3| unix

В приведенном выше примере "span" для "unix" будет 2 (3-1).

До сих пор я пытался использовать grep -n, но я не думаю, что grep достаточно мощный. Может быть, какое-то использование sed или awk?

Спасибо!

3 ответа3

4

Использование awk

команда

awk '{ if($0 ~ /PATTERN/) { if(!FIRST) FIRST=NR; LAST=NR } } END { print LAST-FIRST }' FILE

Как это устроено

  • awk '{ COMMANDS } END { FINALCOMMAND }' FILE выполняет COMMMANDS для каждой строки FILE .

    После этого он выполняет FINALCOMMAND .

  • if($0 ~ /PATTERN/) { ... } проверяет, встречается ли PATTERN в строке ($0).

    Если это так, ... исполняется.

  • The first time the pattern occurs, FIRST` будет пустым.

    Поэтому if(!FIRST) FIRST=NR сохранит номер строки (NR) в FIRST .

  • Для каждого случая LAST=NR будет хранить номер строки (NR) в LAST .

    После обработки всех вхождений LAST будет содержать номер строки последнего вхождения.

  • print LAST-FIRST печатает разницу между номером последней и первой строки.


Используя только grep , head и tail

скрипт

MATCHES=$(grep -n PATTERN FILE)
FIRST=$(echo "$MATCHES" | head -n 1 | grep -Po "^\d+"); [ $FIRST ] || FIRST=0
LAST=$(echo "$MATCHES" | tail -n 1 | grep -Po "^\d+"); [ $LAST ] || LAST=0
SPAN=$(($LAST - $FIRST))

Как это устроено

  • grep -n PATTERN FILE показывает все строки в FILE соответствующие PATTERN , с предшествующим их номером строки.

  • echo "$MATCHES" | head -n 1 показывает первую строку MATCHES , а grep -Po "^ *\d+" отфильтровывает все, кроме номера строки.

    После этого. [ $FIRST ] || FIRST=0 проверяет, был ли определен FIRST . Если это не так, он устанавливается в 0 .

  • echo "$MATCHES" | tail -n 1 показывает последнюю строку MATCHES , а grep -Po "^ *\d+" отфильтровывает все, кроме номера строки.

    После этого. [ $LAST ] || LAST=0 проверяет, был ли задан LAST . Если это не так, он устанавливается в 0 .

  • $(($LAST - $FIRST)) вычисляет разницу между номером последней и первой строки.

0

Это может работать для вас:

sed '/unix/=;d' file | sed '1h;$!d;G;s/\n/-/' | bc
0

Это найдет промежуток между первым и последним вхождением слова (т.е. промежуточные слова не учитываются)...

Примечание. Команды sed i и a (вставка и добавление) должны быть последней командой в строке.

eval "$(sed -ne "1 i b=
                 /\<$word\>/{=; i ;e=
                 =}
                 $ {a ;echo \$((e-b))
                 }
                " "$file" | tr -d '\n')"

Или это один, который трубы СЭД к СЭД, но, пожалуй , проще.

eval "$(sed -n "/\<$word\>/=" "$file" |
        sed -n '1{i b=
             p};${i;e=
             p;   a;echo \$((e-b))
              }' | tr -d '\n')"   

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .