Удалите строки на основе шаблона, но хранения первых n строк то соответствие

В общем случае проблемы как это происходят из-за mistmatch между тем, что отправляет эмулятор терминала и что ожидает клиентское приложение.

Различные эмуляторы терминала имеют другую степень настраиваемости, таким образом ознакомление себя с эмуляцией tunables конкретной необходимо.

Клиентские приложения зависят от значения $TERM который привык к терминалу поиска (эмулятор) возможности в terminfo (или termcap) база данных.

В Вашем случае Ваша emacs привязка использует явные последовательности таким образом $TERM и terminfo не важны: определенный эмулятор терминала ожидается - когда Вы уже выяснили, a xterm- совместимый.

6
18.11.2018, 08:50
5 ответов

Если Вы хотите удалить все строки, запускающиеся с %, помещенного, сохраняя первые две строки входа, Вы могли сделать:

sed -e 1,2b -e '/^%/d'

Хотя то же было бы более четким с awk:

awk 'NR <= 2 || !/^%/'

Или, если Вы после производительности:

{ head -n 2; grep -v '^%'; } < input-file

Если Вы хотите сохранить первые две строки, соответствующие шаблону, в то время как они не могут быть первыми входа, awk конечно, был бы более оптимальный вариант:

awk '!/^%/ || ++n <= 2'

С sed, Вы могли использовать приемы как:

sed -e '/^%/!b' -e 'x;/xx/{h;d;}' -e 's/^/x/;x'

Таким образом, используйте пространство хранения для подсчета количества случаев шаблонов подобранным до сих пор. Не ужасно эффективный или четкий.

10
27.01.2020, 20:21
  • 1
    Спасибо @Stephane. Это работало. Спасибо за дополнительную информацию также. –  Jana 18.01.2013, 19:42

Я боюсь sed один немного слишком просто для этого (не, что это было бы невозможно, скорее сложный - видят, например, sed sokoban для того, что может быть сделано).

Как насчет awk?

#!/bin/awk -f
BEGIN { c = 0; }
{
    if (/^%/) {
        if (c++ < 3) {
            print;
        }
    } else {
        print;
    }
}

Если можно полагаться на использование достаточно недавнего Bash (который поддерживает регулярные выражения), awk выше может быть переведен в:

#!/bin/bash -
c=0
while IFS= read -r line; do
    if [[ $line =~ ^% ]]; then
        if ((c++ < 3)); then
            printf '%s\n' "$line"
        fi
    else
        printf '%s\n' "$line"
    fi
done

Можно также использовать sed или grep сделать сопоставление с образцом вместо =~ оператор.

3
27.01.2020, 20:21
  • 1
    Соответствовать строке, запускающейся с % в оболочке, никакой потребности в regexps или ksh/bash определенных функциях как [[, можно использовать case $line in %*). Выполнение его этот путь с оболочками, особенно колотите, будет ужасно неэффективным. Используя циклы в оболочках обычно считается плохой практикой. –  Stéphane Chazelas 18.01.2013, 11:17
  • 2
    Спасибо @peterph. Так как мои файлы огромны, я действительно искал что-то как ответ Stephane. Еще раз спасибо –  Jana 18.01.2013, 19:44
  • 3
    @Jana Без проблем, мне, не было просто действительно ясно, как ли строки, соответствующие ему шаблон, предполагалось, были только в начале файла или вкраплены остальными. Вот почему я использовал циклы. –  peterph 19.01.2013, 00:28

Решение острот Perl:

# in-place editing
perl -i -pe '$.>2 && s/^%.*//s' filename.txt

# print to the standard output
perl -ne '$.>2 && /^%/ || print' filename.txt
2
27.01.2020, 20:21
tr '\n' ';' < input | sed 's/% /##/3g' | tr ';' '\n' | sed '/##/d'

Я заменил символы новой строки''; для получения однострочной строки, затем повернул всех кроме первых двух случаев шаблона в маркировку ## с sed 's/pattern/##/3g' (замена от трети до последнего вхождения шаблона в строке), возвращенный''; к '\n' и наконец удаленным отмеченным строкам.

1
27.01.2020, 20:21
  • 1
    Спасибо @Nykakin. Замена шаблона для моих данных не будет эффективна. Спасибо за Ваш вход –  Jana 18.01.2013, 19:45
sed '/^%/{
3,$d}' '% 1 
% 2
% 3
% 4
% 5
text1
text2
text3'

Один способ удалить дополнительные строки.

Править: мой ответ работает при том же условии как Stephane Chazelasесли строки % не произойдут сначала, то это не будет работать.


Компьютерный фанат, стреляющий из укрытия.

sed -n '/^% [^12]*$/!{
/^% [12][[:digit:]]\{1,\}/n
p}' file.txt

Будет работать независимо от где % number строка найдена в потоке. Любая строка, которая запускается с % и концы с любым количеством символов, кроме того, 1 или 2, который мы инвертируем. Тот адрес соответствует чему-либо, кроме того, /% [A-Za-z3-9]*/ отъезд мертвой зоны. Числа между 10-29 распечатают все еще. Таким образом, мы вкладываем второй адрес, чтобы соответствовать тому диапазону и пропустить строку.

Но awk все еще был бы лучше.

1
27.01.2020, 20:21

Теги

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