как удалить текстовый блок (шаблон) из файла с помощью sed / awk - PullRequest
4 голосов
/ 08 сентября 2011

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

Это не просто блок текста, а шаблон.

<!--
# Translator(s):
#
# username1 <email1>
# username2 <email2>
# usernameN <emailN>
#
-->

В блоке, если он появится, будет указан 1 или более пользователей со своими адресами электронной почты.

Ответы [ 5 ]

1 голос
/ 02 апреля 2013

У меня есть еще одна небольшая awk-программа, которая выполняет задачу в несколько строк кода.Он может быть использован для удаления шаблонов текста из файла.Можно также запустить как start, так и stop.

# This block is a range pattern and captures all lines between( and including )
# the start '<!--' to the end '-->' and stores the content in record $0. 
# Record $0 contains every line in the range pattern.
# awk -f remove_email.awk yourfile

# The if statement is not needed to accomplish the task, but may be useful.
# It says - if the range patterns in $0 contains a '@' then it will print
# the string "Found an email..." if uncommented.

# command 'next' will discard the content of the current record and search
# for the next record.
# At the same time the awk program begins from the beginning.


/<!--/, /-->/ {
    #if( $0 ~ /@/ ){
        # print "Found an email and removed that!"
    #}
next
}

# This line prints the body of the file to standard output - if not captured in
# the block above.
1 {
    print
}

Сохраните код в 'remove_email.awk' и запустите его: awk -f remove_email.awk yourfile

1 голос
/ 19 ноября 2011

Это решение может работать:

 sed '/^<!--/,/^-->/{/^<!--/{h;d};H;/^-->/{x;/^<!--\n# Translator(s):\n#\(\n# [^<]*<email[0-9]\+>\)\+\n#\n-->$/!p};d}' file

Альтернатива (возможно, лучшее решение?):

sed '/^<!--/{:a;N;/^-->/M!ba;/^<!--\n# Translator(s):\n#\(\n# \w\+ <[^>]\+>\)+\n#\n-->/d}' file

Это собирает строки, которые начинаются с <!-- и заканчиваются -->, затем сопоставления с образцом в коллекции, т. Е. Вторая строка # Translator(s):, третья строка #, четвертая и, возможно, больше строк следуют # username <email address>, предпоследняя строка #, а последняя строка -->. Если сопоставление выполнено, вся коллекция удаляется, иначе она печатается как обычно.

0 голосов
/ 08 сентября 2011

Вот мое решение, если я правильно понял вашу проблему.Сохраните следующее в файл с именем remove_blocks.awk:

# See the beginning of the block, mark it
/<!--/ {
    state = "block_started" 
}

# At the end of the block, if the block does not contain email, print
# out the whole block.
/^-->/ {
    if (!block_contains_user_email) {
        for (i = 0; i < count; i++) {
            print saved_line[i];
        }
        print
    }

    count = 0
    block_contains_user_email = 0
    state = ""
    next
}

# Encounter a block: save the lines and wait until the end of the block
# to decide if we should print it out
state == "block_started" {
    saved_line[count++] = $0
    if (NF>=3 && $3 ~ /@/) {
        block_contains_user_email = 1
    }
    next
}

# For everything else, print the line
1

Предположим, что ваш текстовый файл находится в файле data.txt (или, если на то пошло, много файлов):

awk -f remove_blocks.awk data.txt

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

0 голосов
/ 08 сентября 2011
perl -i.orig -00 -pe 's/<!--\s+#\s*Translator.*?\s-->//gs' file1 file2 file3
0 голосов
/ 08 сентября 2011

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

Другое решение, но не очень эффективное, будет:

sed "s/-->/&\n/;s/<!--/\n&/" file |  awk 'BEGIN {RS = "";FS = "\n"}/username/{print}'

HTH Крис

...