Как я могу удалить строки, начинающиеся с «//» (например, заголовок файла), которые находятся в начале файла? - PullRequest
4 голосов
/ 10 июля 2020

Я хочу удалить заголовок из всех файлов, и в заголовке есть строки, начинающиеся с //.

Если я хочу удалить все строки, начинающиеся с //, я могу сделать следующее:

sed '/^\/\//d'

Но это не то, что мне нужно делать. Мне просто нужно удалить строки в начале файла, который начинается с //.

Образец файла:

// This is the header
// This should be deleted
print "Hi"
// This should not be deleted
print "Hello"

Ожидаемый результат:

print "Hi"
// This should not be deleted
print "Hello"

Обновление: если в начале или между ними есть новая строка, она не работает. Есть ли способ позаботиться об этом сценарии?

Образец файла:

< new empty line >
// This is the header
< new empty line >
// This should be deleted
print "Hi"
// This should not be deleted
print "Hello"

Ожидаемый результат:

print "Hi"
// This should not be deleted
print "Hello"

Может кто-нибудь предложить способ сделать это? Заранее спасибо!

Обновление: принятый ответ хорошо работает для white space в начале или в промежутке.

Ответы [ 6 ]

5 голосов
/ 10 июля 2020

Не могли бы вы попробовать следующее. Это также относится к сценарию новой строки, написанному и протестированному в https://ideone.com/IKN3QR

awk '
(NF == 0 || /^[[:blank:]]*\/\//) && !found{
  next
}
NF{
  found=1
}
1
' Input_file

Пояснение: Простая проверка условий, если строка либо пуста, либо начинается с // И найденная переменная имеет значение NULL, тогда просто пропустите эти строки. Как только будет найдена какая-либо строка без //, тогда установим переменную, найденную здесь, поэтому все следующие следующие строки должны быть напечатаны от строки, в которой она установлена, до конца Input_file.

2 голосов
/ 10 июля 2020

Похоже, вы просто хотите начать печать с первой строки, которая не пуста и не является просто комментарием:

$ awk 'NF && ($1 !~ "^//"){f=1} f' file
print "Hi"
// This should not be deleted
print "Hello"

Приведенное выше просто устанавливает флаг f, когда он находит такую ​​строку и печатает каждую строчку с тех пор. Он будет работать с любым awk в любой оболочке в каждом поле UNIX.

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

Он был протестирован на этом входе:

$ cat file

    // This is the header

// This should be deleted
print "Hi"
// This should not be deleted
print "Hello"

Чтобы запустить вышеуказанное для многих файлов одновременно и изменить каждый файл, как вы, go это с GNU awk:

awk -i inplace 'NF && ($1 !~ "^//"){f=1} f' *

и это с любым awk:

ip_awk() { local f t=$(mktemp) && for f in "${@:2}"; do awk "$1" "$f" > "$t" && mv -- "$t" "$f"; done; }

ip_awk 'NF && ($1 !~ "^//"){f=1} f' *
2 голосов
/ 10 июля 2020

С sed:

sed -n '1{:a; /^[[:space:]]*\/\/\|^$/ {n; ba}};p' file
print "Hi"
// This should not be deleted
print "Hello"

Немного короче версия с GNU sed:

sed -nE '1{:a; /^\s*\/\/|^$/ {n; ba}};p' file

Пояснение:

1 { # execute this block on the fist line only
    :a; # this is a label
     /^\s*\/\/|^$/ { n;  # on lines matching `^\s*\/\/` or `^$`, do: read the next line
          ba }           # and go to label :a
};  # end block
p   # print line unchanged:
    # we only get here after the header or when it's not found

sed -n делает sed не печатать строки без команды p.

Изменить: обновлен шаблон, чтобы также пропускать пустые строки.

1 голос
/ 10 июля 2020

В случае, если perl доступен, это может также работать в режиме slurp:

perl -0777 -pe 's~\A(?:\h*(?://.*)?\R+)+~~' file

\A будет соответствовать только началу файла, а (?:\h*(?://.*)?\R+)+ будет соответствовать 1 или более строкам, которые пустым или укажите // с необязательными ведущими пробелами.

1 голос
/ 10 июля 2020

С GNU sed:

sed -i -Ez 's/^((\/\/[^\n]*|\s*)\n)+//' file

Выражение ^((\/\/[^\n]*|\s*)\n)+ будет соответствовать одной или нескольким строкам, начинающимся с //, также совпадающим с пустыми строками, только в начале файла.

0 голосов
/ 11 июля 2020

Использование ed ( файл редактор, на котором основан поток редактор sed),

printf '1,/^[^/]/ g|^\(//.*\)\{0,1\}$| d\nw\n' | ed tmp.txt

Некоторые объяснения, вероятно, в порядке.

ed принимает имя файла для редактирования в качестве аргумента и считывает команды из стандартного ввода. Каждая команда заканчивается новой строкой. (Вы также можете читать команды из документа здесь, а не из printf через канал.)

  1. 1,/^[^/]/ адресует первые строки в файле, вплоть до первой, которая не начинается с /. (Все строки, которые вы хотите удалить, будут включены в этот набор.)
  2. g|^\(//.*\)\{0,1\}$|d удаляет все адресованные строки, которые либо пусты, либо do начинаются с //.
  3. w сохраняет изменения.

Шаг 2 немного некрасивый; к сожалению, ed не поддерживает операторы регулярных выражений, которые вы можете принять как должное, например ? или |. Небольшое разрушение регулярного выражения:

  1. ^ соответствует началу строки.
  2. //.* соответствует //, за которым следует ноль или более символов.
  3. \(//.*\)\{0,1\} соответствует предыдущему регулярному выражению 0 или 1 раз (т. Е. Необязательно)
  4. $ соответствует концу строки.
...