Awk для замены одинарной кавычки - PullRequest
4 голосов
/ 25 февраля 2010

Я хочу заменить все include('./ в наборе файлов на include('. Я пытаюсь использовать awk следующим образом:

awk '{gsub("include\('"'"'./", "include\('"'"'", $0); print > FILENAME}' *.php

Это сбрасывает меня с этой ошибки.

awk: (FILENAME=xyz.php FNR=1) fatal: Unmatched ( or \(: /include('.//

Любая помощь будет оценена.

Ответы [ 4 ]

12 голосов
/ 25 февраля 2010

@ OP, вы можете попробовать использовать восьмеричный код для одинарной кавычки (\047) и косой черты (\057), например

$ cat file
include('./
$ awk '{gsub(/include\(\047\.\057/ , "include(\047" ) }1' file
include('
2 голосов
/ 25 февраля 2010

Это работает (без перенаправления ввода / вывода на «печать»):

awk '{gsub(/include\('"'"'.\//, "include\('"'"'", $0); print }' # Wrong
awk '{gsub(/include\('"'"'.\//, "include('"'"'", $0); print }'  # Right

Он отображает этот вход:

include('./abc')
include('x/abc')

до:

include('abc')
include('abc')

Опытным путем кажется, что регулярное выражение должно быть внутри косой черты; замещающая строка должна быть обычной строкой. Вам нужно будет сопоставить '.' с '\.', чтобы остановить вторую замену.

Я не очень доволен этим объяснением. Справочная страница для «awk» в MacOS X гласит:

/ re / - постоянное регулярное выражение; любая строка (константа или переменная) может использоваться в качестве регулярного выражения, за исключением положения изолированного регулярного выражения в шаблоне.

Итак, теоретически, используемая вами строковая форма должна работать. Эмпирически, это не так; Я получил практически то же сообщение об ошибке, что и вы с вашим кодом. И вы получили правильные кавычки оболочки, что нетривиально.

В некоторых случаях Perl может быть проще (потому что вы можете выбрать произвольный разделитель для обозначения границ регулярного выражения):

perl -pe "s%include\('\./%include('%g"
0 голосов
/ 28 февраля 2010

Вам не нужно использовать awk, если все, что вы хотите сделать, это. :) Кроме того, запись в файл, когда вы читаете из него, так, как вы это сделали, приведет к потере или повреждению данных , попробуйте не делать этого.

for file in *.php ; do
# or, to do this to all php files recursively:
# find . -name '*.php' | while read file ; do
  # make backup copy; do not overwrite backup if backup already exists
  test -f $file.orig || cp -p $file $file.orig
  # awk '{... print > NEWFILE}' NEWFILE="$file" "$file.orig"
  sed -e "s:include('\./:include(':g" "$file.orig" >"$file"
done

Просто чтобы прояснить аспект потери данных: когда awk (или sed) начнет обработку файла и вы попросите их прочитать первую строку, они фактически выполнят буферизованное чтение, то есть они будут читать из файловая система (давайте упростим и скажем «с диска») блок данных размером с их внутренний буфер чтения (например, 4-65 КБ) для повышения производительности (за счет уменьшения дискового ввода-вывода.) Предположим, что файл работа с размером больше, чем размер буфера. Дальнейшие чтения будут продолжать поступать из буфера, пока буфер не будет исчерпан, после чего второй диск данных будет загружен с диска в буфер и т. Д.

Однако, сразу после того, как вы прочитали первую строку, т.е. после того, как первый блок данных прочитан с диска в буфер, ваш скрипт awk открывает FILENAME, сам входной файл, для записи с усечением , то есть размер файла на диске сбрасывается до 0 . На этом этапе все, что осталось от вашего исходного файла, это первые несколько килобайт данных в памяти awk. Awk будет с радостью продолжать читать строку за строкой из буфера в памяти и производить вывод до тех пор, пока буфер не будет исчерпан, в этот момент awk, вероятно, остановится и оставит вас с файлом 4-65k.

В качестве примечания: если вы на самом деле используете awk для расширения (например, print "PREFIX: " $0), а не для сжатия (gsub(/.../, "")), данных, то вы почти наверняка получите неотвечающий awk и постоянно растущий файл. :)

0 голосов
/ 25 февраля 2010

Попробуйте это:

awk '{gsub("include(\'"'"'./", "include\('"'"'", $0); print > FILENAME}' *.php

вы вернули обратную косую черту

или это:

 awk '{gsub("include(\'./", "include(\'", $0); print > FILENAME}' *.php

как насчет этого?

awk '{gsub("include(\47./", "include(\47", $0); print > FILENAME}' *.php

Вы пытались ничего не скрывать

awk '{gsub("include('./", "include('", $0); print > FILENAME}' *.php
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...