grep -v: Как исключить только первые (или последние) N совпадающих строк?

При установке

DEFAULT_VERSIONS=python=3.5 python2=2.7 python3=3.5

в /etc/make.conf вы должны перестроить порты, которые используют версию Python по умолчанию.

6
14.10.2017, 13:57
5 ответов

sed предоставляет более простой способ:

... |  sed '/some stuff/ {N; s/^.*\n//; :p; N; $q; bp}' | ...

Таким образом вы удаляете первое вхождение.

Если вы хотите больше:

sed '1 {h; s/.*/iiii/; x}; /some stuff/ {x; s/^i//; x; td; b; :d; d}'

, где количество ] i - количество вхождений (одно или несколько, не ноль).

Многострочное объяснение

sed '1 {
    # Save first line in hold buffer, put `i`s to main buffer, swap buffers
    h
    s/^.*$/iiii/
    x
}

# For regexp what we finding
/some stuff/ {
    # Remove one `i` from hold buffer
    x
    s/i//
    x
    # If successful, there was `i`. Jump to `:d`, delete line
    td
    # If not, process next line (print others).
    b
    :d
    d
}'

Вдобавок

Вероятно, этот вариант будет работать быстрее, потому что он считывает все оставшиеся строки и печатает их за один раз

sed '1 {h; s/.*/ii/; x}; /a/ {x; s/i//; x; td; :print_all; N; $q; bprint_all; :d; d}'

В результате

Вы можете поместить этот код в свой .bashrc (или в конфиг вашей оболочки, если он другой):

dtrash() {
    if [ $# -eq 0 ]
    then
        cat
    elif [ $# -eq 1 ]
    then
        sed "/$1/ {N; s/^.*\n//; :p; N; \$q; bp}"
    else
        count=""
        for i in $(seq $1)
        do
            count="${count}i"
        done
        sed "1 {h; s/.*/$count/; x}; /$2/ {x; s/i//; x; td; :print_all; N; \$q; bprint_all; :d; d}"

    fi
}

И использовать его так:

# Remove first occurrence
cat file | dtrash 'stuff' 
# Remove four occurrences
cat file | dtrash 4 'stuff'
# Don't modify
cat file | dtrash
2
27.01.2020, 20:27

Вы можете использовать awk , чтобы игнорировать первые n совпадающие строки (например, предполагая, что вы хотите удалить только 1-е и 2-е совпадения из файла) :

n=2
awk -v c=$n '/PATTERN/ && i++ < c {next};1' infile

Чтобы игнорировать последние n совпадающие строки:

awk -v c=${lasttoprint} '!(/PATTERN/ && NR > c)' infile

где $ {lasttoprint} - это номер строки n th + 1 для последнее совпадение в вашем файле. Есть разные способы получить этот номер строки. (например, распечатайте только номер строки для каждого совпадения с помощью таких инструментов, как sed / awk , затем tail | head , чтобы извлечь его) ... вот один способ с GNU awk :

n=2
lasttoprint=$(gawk -v c=$((n+1)) '/PATTERN/{x[NR]};
END{asorti(x,z,"@ind_num_desc");{print z[c]}}' infile)
5
27.01.2020, 20:27

Возможно, уменьшите шансы отфильтровать ваши данные с помощью более точной команды grep. Например:

grep -v -F -x 'str1'

Для строк, которые являются точно str1. Или может быть:

grep -v '^str1.*str2$'

Для строк, которые начинаются с 'str1' и заканчиваются 'str2'.

0
27.01.2020, 20:27

Para hacer esto, es posible que deba usar awk.

La manera simple que sé es esta:

cat file | awk '{ $1=""; print}'

También puede omitir varias columnas:

cat file | awk '{ $1=$2=$3=""; print}'

Si desea omitir la última columna y no está seguro de cuántas columnas tendrá:

cat file | awk '{ $NF=""; print}'

Probado en Ubuntu 16.04 (GNU bash, versión 4.3.48)

Mejor.

0
27.01.2020, 20:27

Другим возможным решением является использование собственных утилит bash:

count=1
found=0
cat execute-commons-fileupload.sh | while read line
do 
   if [[ $line == *"myPattern"* ]]
   then 
      if [ $found -eq $count ]
      then 
         echo "$line"
      else 
         found=$(($found+1))
      fi
   else 
     echo "$line"
   fi
done

Установив количество, вы можете изменить количество вхождений шаблона, который вы хотите удалить.

Лично мне это кажется более простым для расширения, так как вы можете легко добавить другие условия к оператору if(, но это может быть вызвано моими незначительными знаниями о sed ).

0
22.07.2020, 12:21

Теги

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