Есть ли утилита командной строки приложение, которое может найти определенный блок строк в текстовом файле, и заменить его?

Существуют разные серверы от всех менеджеров доменных имен верхнего уровня, каждый с разными ограничениями. Кроме того, многие из этих управляющих объектов изменяют пределы по отношению к текущей нагрузке на свои серверы. Некоторые из них добавляют немного времени к вашему запрету для каждого отклоненного запроса, некоторые - нет. Это просто сложно сказать.

Некоторые серверы whois, такие как whois.iana.org (который содержит информацию обо всех именах верхнего уровня, таких как «net» и «org»), вообще не ограничивают подключения. Немецкий, как мне сказали, начинает жаловаться после нескольких миллионов запросов. Некоторые из серверов, которые отвечают за менее известные имена верхнего уровня, могут заблокировать ваш доступ только после нескольких сотен запросов.

Если вы достигли предела и заблокированы, это еще не конец света. Вам либо придется ждать, пока ваш запрет будет отменен, либо - если применимо - для изменения вашего IP-адреса. Я бы предположил, что несколько тысяч должны быть в порядке.

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

7
задан 10 January 2011 в 00:30

48 ответов

Этот простой скрипт python должен выполнить задачу:


#!/usr/bin/env python

# Syntax: multiline-replace.py input.txt search.txt replacement.txt

import sys

inp = open(sys.argv[1]).read()
needle = open(sys.argv[2]).read()
replacement = open(sys.argv[3]).read()

sys.stdout.write(inp.replace(needle,replacement))

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

7
ответ дан 25 May 2018 в 23:35
  • 1
    Ну теперь! Это путь! ... Я все бросил на него, и он выдержал испытание .. (и почему бы и нет ... Python имеет «репутацию» по уважительной причине.;) .... Мне нужно посмотреть далее в "замену" метод (или что-то типа Python их называет) .. но .. она зов! ... Спасибо.loevborg .. – Peter.O 10 January 2011 в 00:04

даже если Вы не любите седой [F2] и perl, вы можете по-прежнему найти вкус в серой-templed awk. Этот ответ, кажется, то, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и хотите заменить needle с replacement в haystack:

awk ' BEGIN { RS="" } FILENAME==ARGV[1] { s=$0 } FILENAME==ARGV[2] { r=$0 } FILENAME==ARGV[3] { sub(s,r) ; print } ' needle replacement haystack > output

это не связано с регулярными выражениями и поддерживает символы новой строки. Это похоже на работу с достаточно большими файлами. Оно связано чавкать весь файл в память, поэтому он не будет работать с файлами произвольного размера. Если вы хотите его более элегантным, вы можете приложить всю эту историю в bash-скрипт, или превратить его в awk скрипт.

7
ответ дан 26 July 2018 в 23:20

Даже если вам не нравятся седые sed и perl, вы все равно можете найти симпатию к серому awk. Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить needle на replacement в haystack:

awk ' BEGIN { RS="" } FILENAME==ARGV[1] { s=$0 } FILENAME==ARGV[2] { r=$0 } FILENAME==ARGV[3] { sub(s,r) ; print } ' needle replacement haystack > output

. Это не связано с регулярными выражениями и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете вложить весь shebang в сценарий bash или превратить его в скрипт awk.

7
ответ дан 31 July 2018 в 11:11

Этот простой скрипт python должен выполнить задачу:

#!/usr/bin/env python # Syntax: multiline-replace.py input.txt search.txt replacement.txt import sys inp = open(sys.argv[1]).read() needle = open(sys.argv[2]).read() replacement = open(sys.argv[3]).read() sys.stdout.write(inp.replace(needle,replacement))

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

7
ответ дан 31 July 2018 в 12:09

Даже если вам не нравятся седые sed и perl, вы все равно можете найти симпатию к серому awk. Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить needle на replacement в haystack:

awk ' BEGIN { RS="" } FILENAME==ARGV[1] { s=$0 } FILENAME==ARGV[2] { r=$0 } FILENAME==ARGV[3] { sub(s,r) ; print } ' needle replacement haystack > output

. Это не связано с регулярными выражениями и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете вложить весь shebang в сценарий bash или превратить его в скрипт awk.

7
ответ дан 2 August 2018 в 04:05

Даже если вам не нравится седло sed и perl , вы все равно можете найти симпатию к серо-образному awk . Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить иглу заменой в haystack :

  awk 'BEGIN {  RS = ""} FILENAME == ARGV [1] {s = $ 0} FILENAME == ARGV [2] {r = $ 0} FILENAME == ARGV [3] {sub (s, r);  print} 'output haystack> output  

Это не включает регулярные выражения и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете заключить весь shebang в сценарий bash или превратить его в скрипт awk .

7
ответ дан 4 August 2018 в 20:08

Даже если вам не нравится седло sed и perl , вы все равно можете найти симпатию к серо-образному awk . Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить иглу заменой в haystack :

  awk 'BEGIN {  RS = ""} FILENAME == ARGV [1] {s = $ 0} FILENAME == ARGV [2] {r = $ 0} FILENAME == ARGV [3] {sub (s, r);  print} 'output haystack> output  

Это не включает регулярные выражения и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете заключить весь shebang в сценарий bash или превратить его в скрипт awk .

7
ответ дан 6 August 2018 в 04:10

Этот простой скрипт python должен выполнить задачу:

  #! / usr / bin / env python # Синтаксис: multiline-replace.py input.txt search.txt replacement.txt import sys  inp = open (sys.argv [1]). read () needle = open (sys.argv [2]). read () replacement = open (sys.argv [3]). read () sys.stdout.write  (inp.replace (игла, замена))  

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

7
ответ дан 7 August 2018 в 22:09

Даже если вам не нравится седло sed и perl , вы все равно можете найти симпатию к серо-образному awk . Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить иглу заменой в haystack :

  awk 'BEGIN {  RS = ""} FILENAME == ARGV [1] {s = $ 0} FILENAME == ARGV [2] {r = $ 0} FILENAME == ARGV [3] {sub (s, r);  print} 'output haystack> output  

Это не включает регулярные выражения и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете заключить весь shebang в сценарий bash или превратить его в скрипт awk .

7
ответ дан 10 August 2018 в 10:23

Даже если вам не нравится седло sed и perl , вы все равно можете найти симпатию к серо-образному awk . Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить иглу заменой в haystack :

  awk 'BEGIN {  RS = ""} FILENAME == ARGV [1] {s = $ 0} FILENAME == ARGV [2] {r = $ 0} FILENAME == ARGV [3] {sub (s, r);  print} 'output haystack> output  

Это не включает регулярные выражения и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете заключить весь shebang в сценарий bash или превратить его в скрипт awk .

7
ответ дан 13 August 2018 в 16:48
  • 1
    Я, должно быть, дал неправильное сообщение. Я LOVE 'sed'! и использовать его для всех вещей под солнцем ... Я просто думаю, что это не лучший инструмент для этой работы .... Я собираюсь опубликовать решение «sed», которое работает, и НЕ будет проблемы с вызовом специальных символов регулярных выражений, но я чувствую, что он создает слишком много файлов и поэтому является «тяжелым». для работы ...... После того, как я разместил его и сделал перерыв, я хорошо рассмотрю ваше решение. Спасибо ... – Peter.O 9 January 2011 в 17:37
  • 2
    .. К сожалению, по отношению к специальным символам регулярного выражения, если они не совпадают, а также все регулярные выражения. Когда они сталкиваются с специальным символом , они обрабатывают его особым образом. Нехорошо, когда не предназначен для специальных. Он разбился на [, ( и ложные результаты на $ , ^ (не нашли данные, даже хотя он был идентичен) ... Я больше не проверял ... (Но команда выглядит «правильно» и :) – Peter.O 9 January 2011 в 20:56
  • 3
    Фред, ты прав; Я должен был проверить документацию. Более того gsub представляется более подходящим, чем sub . Мне кажется странным, что не появилась простая утилита поиска / замены mulitline nonregex. Кажется, что нет простого способа ускользания / цитирования поисковой иглы (в perl , например, с помощью quotemeta ). – loevborg 9 January 2011 в 21:43
  • 4
    Я только что узнал о grep -F --fixed-strings . Это ставит grep в совершенно новую категорию (для меня) ... как read -r ... буквальная интерпретация .. Если бы это было sed , это было бы все очень просто .. (возможно, awk имеет что-то вроде этого (?) .... и btw. Простейшая часть всего этого заключается в замене строк: простая head (после идентификации первого номера строки) | замена кошки | хвост остальное (длина удаленной части известна) ... Итак, теперь с grep -F -A {num} это может быть сшито скоро :) – Peter.O 9 January 2011 в 22:26
  • 5
    Ну теперь! Это путь! ... Я все бросил на него, и он выдержал испытание .. (и почему бы и нет ... Python имеет «репутацию» по уважительной причине.;) .... Мне нужно посмотреть далее в "замену" метод (или что-то типа Python их называет) .. но .. она зов! ... Спасибо.loevborg .. – Peter.O 10 January 2011 в 00:04

Этот простой скрипт python должен выполнить задачу:

  #! / usr / bin / env python # Синтаксис: multiline-replace.py input.txt search.txt replacement.txt import sys  inp = open (sys.argv [1]). read () needle = open (sys.argv [2]). read () replacement = open (sys.argv [3]). read () sys.stdout.write  (inp.replace (игла, замена))  

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

7
ответ дан 15 August 2018 в 23:30
  • 1
    Ну теперь! Это путь! ... Я все бросил на него, и он выдержал испытание .. (и почему бы и нет ... Python имеет «репутацию» по уважительной причине.;) .... Мне нужно посмотреть далее в "замену" метод (или что-то типа Python их называет) .. но .. она зов! ... Спасибо.loevborg .. – Peter.O 10 January 2011 в 00:04

Подход 1: временно изменить новые строки на что-то еще

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

<old.txt tr '\n' '|' |
sed 's/\(|\|^\)'\''Twas … toves|Did … Bandersnatch!'\''|/new line 1|new line 2|/g' |
tr '|' '\n' >new.txt

Подход 2: изменение разделителя записей утилиты

Поддержка Awk и perl, поддерживающая два или более пустые строки в качестве разделителя записей. С awk передайте -vRS= (пустая переменная RS). С помощью Perl пройдите -000 («режим абзаца») или установите $,="". Это не полезно здесь, так как у вас есть строка поиска с несколькими пунктами.

Awk и perl также поддерживают установку любой строки в качестве разделителя записей. Установите RS или $, на любую строку, которая не находится в вашей строке поиска.

<old.txt perl -pe '
    BEGIN {$, = "|"}
    s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg
' >new.txt

Подход 3: работа над всем файлом

Некоторые утилиты легко позволяют вам читать весь файл в память и работать над ним.

<old.txt perl -0777 -pe '
    s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg
' >new.txt

Подход 4: program

Прочитайте строки один за другим. Начните с пустого буфера. Если вы видите строку «Twas» и буфер пуст, поместите ее в буфер. Если вы видите «Did gyre» и есть одна строка в буфере, добавьте текущую строку в буфер и так далее. Если вы только что добавили строку «Bandersnatch», выведите заменяющий текст. Если текущая строка не попала в буфер, напечатайте содержимое буфера, распечатайте текущую строку и очистите буфер.

psusi показывает реализацию sed. В sed концепция буфера встроена; это называется удерживающим пространством. В awk или perl вы просто используете переменную (возможно, две, одну для содержимого буфера и одну для количества строк).

3
ответ дан 25 May 2018 в 23:35
  • 1
    Жиль, спасибо за варианты. Как я уже упоминал в других комментариях, я исключил все, что использует регулярное выражение. Потому что мой текст поиска в какой-то момент столкнется с специальными символами регулярных выражений .. Я подумал, что что-то вроде этого может быть хорошо известно в царствах кодера (исходные коды), но, возможно, нет ... Я рассмотрю awk немного позже, но я подозреваю, что read -r (я только что открыл -r сегодня) может быть способом ... Я написал рабочий скрипт на прошлой неделе, который не использует регулярное выражение, но я уже знал, где найти текст (через его номер строки). read -r или awk могут работать для поиска в неизвестном файле. – Peter.O 9 January 2011 в 07:22
  • 2
    @ fred.bear: поиск текста, содержащего специальные символы регулярного выражения, является отдельной проблемой. Один из способов его решения - препроцитировать строку поиска, чтобы указать специальные символы. Лучший способ, если утилита поддерживает его, - выполнить строчный поиск по строкам. Awk: index. Perl: функция index, \Q…\E escape-выход. – Gilles 9 January 2011 в 15:51
  • 3
    Gilles, инструменту нужно будет поддерживать не только литеральный поиск строк, но и буквальную замену строк. – loevborg 9 January 2011 в 21:48
  • 4
    @loevborg: В Perl это просто s/\Q$needle/$haystack/g. Awk менее прост, но выполним. – Gilles 9 January 2011 в 21:59

Я был уверен, что должен был быть способ сделать это с sed. После некоторого googling я наткнулся на это:

http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/

Основано на что я закончил писать:

sed -n '1h;1!H;${;g;s/foo\nbar/jar\nhead/g;p;}' < x

Что правильно взяло содержимое x:

foo bar

И выплюнуть :

jar head

2
ответ дан 25 May 2018 в 23:35
  • 1
    Я бы не стал рекомендовать sed здесь. Хотя он может это сделать, использование пространства удержания быстро усложняется (здесь, с тремя линиями, это уже беспорядок). – Gilles 9 January 2011 в 00:05
  • 2
    Это, безусловно, заставило меня разобраться. Я использую sed (и так далее), но, как сказал Жиль, работа с пространством удержания может быстро стать болью (поэтому я стараюсь держаться подальше от него). Однако самая большая проблема с любым поиском регулярных выражений - это когда ваш шаблон регулярного выражения & Quot; неизвестно & Quot ;; вероятность столкновения высока ... Поэтому я исключаю все, что использует regex. Главное, чтобы избежать ручной настройки ... Честно говоря, если sed имеет некоторый способ поворота off regex, то его функция address может быть очень полезной , в противном случае это не инструмент для работы .. спасибо хотя; Хорошая беседа – Peter.O 9 January 2011 в 06:26

Даже если вам не нравятся седые sed и perl, вы все равно можете найти симпатию к серому awk. Этот ответ кажется тем, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и вы хотите заменить needle на replacement в haystack:


awk ' BEGIN { RS="" }
      FILENAME==ARGV[1] { s=$0 }
      FILENAME==ARGV[2] { r=$0 }
      FILENAME==ARGV[3] { sub(s,r) ; print }
    ' needle replacement haystack > output

. Это не связано с регулярными выражениями и поддерживает символы новой строки. Кажется, он работает с достаточно большими файлами. Это связано с разрывом всего файла в памяти, поэтому он не будет работать с файлами произвольного размера. Если вы хотите, чтобы он был более изящным, вы можете вложить весь shebang в сценарий bash или превратить его в скрипт awk.

2
ответ дан 25 May 2018 в 23:35
  • 1
    Я, должно быть, дал неправильное сообщение. Я LOVE 'sed'! и использовать его для всех вещей под солнцем ... Я просто думаю, что это не лучший инструмент для этой работы .... Я собираюсь опубликовать решение «sed», которое работает, и НЕ будет проблемы с вызовом специальных символов регулярных выражений, но я чувствую, что он создает слишком много файлов и поэтому является «тяжелым». для работы ...... После того, как я разместил его и сделал перерыв, я хорошо рассмотрю ваше решение. Спасибо ... – Peter.O 9 January 2011 в 17:37
  • 2
    .. К сожалению, по отношению к специальным символам регулярного выражения, если они не совпадают, а также все регулярные выражения. Когда они сталкиваются с специальным символом , они обрабатывают его особым образом. Нехорошо, когда не предназначен для специальных. Он разбился на [, ( и ложные результаты на $, ^ (не нашел данных, хотя он был идентичным) ... Я не проверял дальше ... (Но команда выглядит «правильно». :) – Peter.O 9 January 2011 в 20:56
  • 3
    Фред, ты прав; Я должен был проверить документацию. Более того gsub представляется более подходящим, чем sub. Мне кажется странным, что не появилась простая утилита поиска / замены mulitline nonregex. Кажется, нет простого способа ускользания / цитирования поисковой иглы (например, в perl с использованием quotemeta). – loevborg 9 January 2011 в 21:43
  • 4
    Я только что узнал о grep -F --fixed-strings. Это ставит grep в совершенно новую категорию (для меня) ... как read -r ... буквальная интерпретация. Если бы это было только sed, все было бы очень просто .. (возможно, awk имеет что-то вроде это (?) .... и btw. Простейшая часть всего этого заключается в замене строк: простая голова (после идентификации первого номера строки) | замена кошки | хвост остальное (длина удаленной части известна) ... Итак, теперь с grep -F -A{num} она может быть сшита скоро :) – Peter.O 9 January 2011 в 22:26

UPDATE: скрипт python от loevborg, безусловно, является самым простым и лучшим решением (в этом нет никаких сомнений), и я очень доволен этим, но я хотел бы указать, что сценарий bash, который я представил (в конце вопрос) нигде не так сложно, как кажется. Я урезал всю отладочную ветвь, которую я использовал для ее проверки .. и здесь она снова не имеет перегруженности (для тех, кто посещает эту страницу). Это в основном sed однострочный с предварительным и пост-шестнадцатеричным преобразованиями:

F=("$haystack"  "$needle"  "$replacement")
for f in "${F[@]}" ; do cat "$f" | hexdump -v -e '1/1 "%02x"' > "$f.hex" ; done
sed -i "s/$(cat "${F[1])}.hex")/$(cat "${F[2])}.hex")/p" "${F[0])}.hex"
cat "${F[0])}.hex" | xxd -r -p > "${F[0])}"
# delete the temp *.hex files.

Просто, чтобы бросить шляпу в кольцо, я придумал решение «sed» который не столкнется с проблемами с UPDATE символами регулярных выражений, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

Я думаю, что он слишком «тяжелый», но он работает и, по-видимому, не ограничен ограничениями на размер. GNU sed имеет неограниченный размер буфера шаблонов, и вот где заканчивается блок строк поиска Hexdumped. Так что в этом отношении все в порядке ...

Я все еще ищу шаблон потому что он будет более гибким в отношении белого пространства (и я бы ожидал, быстрее) ... но до этого .. Это знаменитый мистер Сед. :)

Этот скрипт полностью запущен как есть, и разумно прокомментирован ... Он выглядит больше, чем он есть; У меня всего 7 строк кода. Для полуреалистичного теста он загружает книгу «Алиса через зазеркалье» из Project Gutenberg (363.1 KB) ... и заменяет оригинальное стихотворение Jabberwocky собственной версией строки .. (Интересно, что это не так много другое чтение его назад :)

PS. Я просто понял, что слабость в этом методе заключается в том, что ваш оригинал использует \ r \ n (0xODOA) в качестве новой строки, а ваш «текст в соответствии» сохраняется с помощью \ n (0x0A) .. тогда этот процесс сопоставления мертв вода ... («diff» не имеет таких проблем) ...

# In a text file, replace one block of lines with another block
#
# Keeping with the 'Jabberwocky' theme, 
#  and using 'sed' with 'hexdump', so 
#  there is no possible *special* char clash.
# 
# The current setup will replace only the first instance.
#   Using sed's 'g' command, it cah change all instances. 
#

  lookinglass="$HOME/Through the Looking-Glass by Lewis Carroll"
  jabberwocky="$lookinglass (jabberwocky)"
  ykcowrebbaj="$lookinglass (ykcowrebbaj)"

  ##### This section if FOR TEST PREPARATION ONLY
        fromURL="http://www.gutenberg.org/ebooks/12.txt.utf8"
        wget $fromURL -O "$lookinglass"
        if (($?==0))
        then  echo "Download OK"
        else  exit 1
        fi
        # Make a backup of the original (while testing)
        cp "$lookinglass" "$lookinglass(fromURL)"
        #
        # Extact the poem and write it to a file. (It runs from line 322-359)
        sed -n 322,359p "$lookinglass" > "$jabberwocky"
        cat "$jabberwocky"; read -p "This is the original.. (press Enter to continue)"
        #
        # Make a file containing a replacement block of lines
        tac "$jabberwocky" > "$ykcowrebbaj"
        cat "$ykcowrebbaj"; read -p "This is the REPLACEMENT.. (press Enter to continue)"
  ##### End TEST PREPARATION

# The main process
#
# Make 'hexdump' versions of the 3 files... source, expected, replacement 
  cat "$lookinglass" | hexdump -v -e '1/1 "%02x"' > "$lookinglass.xdig"
  cat "$jabberwocky" | hexdump -v -e '1/1 "%02x"' > "$jabberwocky.xdig"
  cat "$ykcowrebbaj" | hexdump -v -e '1/1 "%02x"' > "$ykcowrebbaj.xdig"
# Now use 'sed' in a safe (no special chrs) way.
# Note, all files are now each, a single line  ('\n' is now '0A')
  sed -i "s/$(cat "$jabberwocky.xdig")/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig"

  ##### This section if FOR CHECKING THE RESULTS ONLY
        # Check result 1
        read -p "About to test for the presence of  'jabberwocky.xdig'  within itself (Enter) "
        sed -n "/$(cat "$jabberwocky.xdig")/p"     "$jabberwocky.xdig"
        echo -e "\n\nA dump above this line, means: 'jabberwocky' is as expected\n" 
        # Check result 2
        read -p "About to test for the presence of  'ykcowrebbaj.xdig'  within itself (Enter) "
        sed -n "/$(cat "$ykcowrebbaj.xdig")/p"     "$ykcowrebbaj.xdig"
        echo -e "\n\nA dump above this line, means: 'ykcowrebbaj' is as expected\n" 
        # Check result 3
        read -p "About to test for the presence of  'lookinglass.xdig'  within itself (Enter) "
        sed -n "/$(cat "$ykcowrebbaj.xdig")/p"     "$lookinglass.xdig"
        echo -e "\n\nA dump above this line, means: 'lookinglass' is as expected\n" 
        # Check result 4
        read -p "About to test for the presence of  'lookinglass.xdig'  within itself (Enter) "
        sed -n "/$(cat "$jabberwocky.xdig")/p"     "$lookinglass.xdig"
        echo -e "\n\nNo dump above this line means: 'lookinglass' is as expected\n"
  ##### End of CHECKING THE RESULTS

# Now convert the hexdump to binary, and overwrite the original
  cat "$lookinglass.xdig" | xxd -r -p > "$lookinglass"
# Echo the "modified" poem to the screen
  sed -n 322,359p "$lookinglass"
  echo -e "\n\nYou are now looking at the REPLACEMENT text (dumped directly from the source 'book'"
2
ответ дан 25 May 2018 в 23:35
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и указать строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только «трепетал». в течение всего этого времени Linux Ubuntu в течение примерно 4 месяцев, поэтому, когда такая идея захватывает меня, она устанавливает цель, и это отлично подходит для получения серьезного ручного решения для bash / general experiance ... но, как я упоминаю в комментариях где-то существует только 7 строк эссенциального кода; остальное - это просто «отладка». материал и dowloadint тестовый файл и т. д. (я многому научился у него ... – Peter.O 10 January 2011 в 00:09

подход 1: временно изменить строки в нечто другое

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

<old.txt tr '\n' '|' | sed 's/\(|\|^\)'\''Twas … toves|Did … Bandersnatch!'\''|/new line 1|new line 2|/g' | tr '|' '\n' >new.txt

подход 2: смените пластинку сепаратора утилиты

поддержка на awk и Perl установка двух или более пустые строки как разделитель записей. С awk, пройти -vRS= (пустой RS переменная). С Perl, пройти -000 (“пункт режим”) или установите для параметра $,="". Это не полезно, вот хоть у тебя есть мульти-пункт строку поиска.

на awk и Perl также поддерживает установку любой строки как разделитель записей. Установить нажать [F8] и [F9] и любую строку, а не в строку поиска.

<old.txt perl -pe ' BEGIN {$, = "|"} s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

подход 3: Работа на весь файл

некоторые утилиты позволят вам легко считывать весь файл в память и работать на нем.

<old.txt perl -0777 -pe ' s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

подход 4: программы

читать по одной линии. Начинать с пустого буфера. Если вы видите “линия тва” и буфер пуст, поместить его в буфер. Если вы видите “сделал круговращение” и там одна строка в буфер, добавить текущую строку в буфер, и так далее. Если вы только что добавленный строке “Брандашмыг”, вывод текста замены. Если текущая строка не идут в буфер, распечатать содержимое буфера, печать текущую строку и пустой буфер.

psusi показывает внедрение СЭД. В СЭД, буфер концепция встроенные; это называется трюм. В awk или Perl, вы бы просто использовать переменную (возможно два, один за содержимое буфера и один для нескольких строк).

3
ответ дан 25 July 2018 в 22:38
  • 1
    Жиль, спасибо за варианты. Как я уже упоминал в других комментариях, я исключила все, что использует регулярное выражение. Потому что мой поиск-текст, в какой-то момент, столкновение с регулярного выражения специальные символы.. я думала, что такое может быть хорошо известна в кодера миров (исходный код модов), а может и нет... я посмотрю на awk немного дальше, но я подозреваю, что read -r (я только что обнаружил -р сегодня) может быть путь, чтобы пойти... я написал сценарий прошлой неделе, что не будет использовать регулярные выражения, но я уже знал, где можно найти текст (по своей линии-номер). read -r или awk может работать для обнаружения в неизвестном файле. – Peter.O 9 January 2011 в 07:22
  • 2
    @ fred.bear: поиск текста, содержащего специальные символы регулярного выражения, является отдельной проблемой. Один из способов его решения - препроцитировать строку поиска, чтобы указать специальные символы. Лучший способ, если утилита поддерживает его, - выполнить строчный поиск по строкам. Awk: index. Perl: функция index, \Q…\E escape-выход. – Gilles 9 January 2011 в 15:51
  • 3
    Жиль, инструмент необходимо поддерживать не только буквальное строке поиска, а также символьную строку замещения. – loevborg 9 January 2011 в 21:48
  • 4
    @loevborg: В Perl это просто s/\Q$needle/$haystack/g. Awk менее прост, но выполним. – Gilles 9 January 2011 в 21:59

я был уверен, что там должен быть способ сделать это с помощью sed. После некоторых погуглив я наткнулся на это:

http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/

основан на том, что я закончил писать:

sed -n '1h;1!H;${;g;s/foo\nbar/jar\nhead/g;p;}' < x

, который правильно взял содержимое x:

Василий Пупкин

и выплюнул:

лысая голова

2
ответ дан 25 July 2018 в 22:38
  • 1
    Я не рекомендую СЭД здесь. В то время как он может сделать это, используя трюм, быстро сложная (здесь, с тремя линиями это уже бардак). – Gilles 9 January 2011 в 00:05
  • 2
    Это, безусловно, меня thingking. Я использую СЭД (и нравится), но как Жиль отметил, работая с Свободное место может быстро стать болью (поэтому я стараюсь держаться подальше от него).. но самая большая проблема с regex поиск, это когда Ваше регулярное выражение картины "неизвестная"; вероятность столкновения высока... так что я исключаю все, что использует регулярное выражение. Главное в этом, чтобы избежать ручной настройки... честно говоря, если ООО имеет несколько способов превращения от регулярное выражение, то его диапазон адресов[!характеристика Д1] может быть очень полезным, иначе это не инструмент для работы.. спасибо; СЭД говорить хорошо говорить – Peter.O 9 January 2011 в 06:26

даже если Вы не любите седой [F2] и perl, вы можете по-прежнему найти вкус в серой-templed awk. Этот ответ, кажется, то, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и хотите заменить needle с replacement в haystack:

awk ' BEGIN { RS="" } FILENAME==ARGV[1] { s=$0 } FILENAME==ARGV[2] { r=$0 } FILENAME==ARGV[3] { sub(s,r) ; print } ' needle replacement haystack > output

это не связано с регулярными выражениями и поддерживает символы новой строки. Это похоже на работу с достаточно большими файлами. Оно связано чавкать весь файл в память, поэтому он не будет работать с файлами произвольного размера. Если вы хотите его более элегантным, вы можете приложить всю эту историю в bash-скрипт, или превратить его в awk скрипт.

2
ответ дан 25 July 2018 в 22:38
  • 1
    Я, должно быть, дал неправильное сообщение. Я LOVE 'sed'! и использовать его для всех вещей под солнцем ... Я просто думаю, что это не лучший инструмент для этой работы .... Я собираюсь опубликовать решение «sed», которое работает, и НЕ будет проблемы с вызовом специальных символов регулярных выражений, но я чувствую, что он создает слишком много файлов и поэтому является «тяжелым». для работы ...... После того, как я разместил его и сделал перерыв, я хорошо рассмотрю ваше решение. Спасибо ... – Peter.O 9 January 2011 в 17:37
  • 2
    .. К сожалению, в отношении регулярного выражения специальные символы, если не удалось в равной степени как и все regex утилиты. Когда они сталкиваются с специальный характер, они относиться к нему по особенному.. не хорошо, когда он не предназначен, чтобы быть особенным. Он разбился на [,( и ложные результаты $,^ (не нашла данных, даже если он был одинаковый)... я не проверял дальше... (но команда выглядит "как надо" :) – Peter.O 9 January 2011 в 20:56
  • 3
    Фред, ты прав; я должен был проверить документацию. Кроме того gsub представляется более целесообразным, чем sub. Я нахожу это довольно странно, что нет простой mulitline поиск nonregex/замене инженерных подвернулся. Там, кажется, нет простого способа вокруг побега/Цитировать поиск иглы (в perl, используя quotemeta например). – loevborg 9 January 2011 в 21:43
  • 4
    Я только что узнал о grep -F --fixed-strings. Это ставит grep в совершенно новую категорию (для меня) ... как read -r ... буквальная интерпретация. Если бы это было только sed, все было бы очень просто .. (возможно, awk имеет что-то вроде это (?) .... и btw. Простейшая часть всего этого заключается в замене строк: простая голова (после идентификации первого номера строки) | замена кошки | хвост остальное (длина удаленной части известна) ... Итак, теперь с grep -F -A{num} она может быть сшита скоро :) – Peter.O 9 January 2011 в 22:26
  • 5
    Ну теперь! Это путь! ... Я все бросил на него, и он выдержал испытание .. (и почему бы и нет ... Python имеет «репутацию» по уважительной причине.;) .... Мне нужно посмотреть далее в "замену" метод (или что-то типа Python их называет) .. но .. она зов! ... Спасибо.loevborg .. – Peter.O 10 January 2011 в 00:04

UPDATE: скрипт python от loevborg, безусловно, является самым простым и лучшим решением (в этом нет никаких сомнений), и я очень доволен этим, но я хотел бы указать, что сценарий bash, который я представил (в конце вопрос) нигде не так сложно, как кажется. Я урезал всю отладочную ветвь, которую я использовал для ее проверки .. и здесь она снова не имеет перегруженности (для тех, кто посещает эту страницу). Это в основном sed однострочный с предварительным и пост-шестнадцатеричным преобразованиями:

F=("$haystack" "$needle" "$replacement") for f in "${F[@]}" ; do cat "$f" | hexdump -v -e '1/1 "%02x"' > "$f.hex" ; done sed -i "s/$(cat "${F[1])}.hex")/$(cat "${F[2])}.hex")/p" "${F[0])}.hex" cat "${F[0])}.hex" | xxd -r -p > "${F[0])}" # delete the temp *.hex files.

Просто, чтобы бросить шляпу в кольцо, я придумал решение «sed» который не столкнется с проблемами с UPDATE символами регулярных выражений, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

Я думаю, что он слишком «тяжелый», но он работает и, по-видимому, не ограничен ограничениями на размер. GNU sed имеет неограниченный размер буфера шаблонов, и вот где заканчивается блок строк поиска Hexdumped. Так что в этом отношении все в порядке ...

Я все еще ищу шаблон потому что он будет более гибким в отношении белого пространства (и я бы ожидал, быстрее) ... но до этого .. Это знаменитый мистер Сед. :)

Этот скрипт полностью запущен как есть, и разумно прокомментирован ... Он выглядит больше, чем он есть; У меня всего 7 строк кода. Для полуреалистичного теста он загружает книгу «Алиса через зазеркалье» из Project Gutenberg (363.1 KB) ... и заменяет оригинальное стихотворение Jabberwocky собственной версией строки .. (Интересно, что это не так много другое чтение его назад :)

PS. Я просто понял, что слабость в этом методе заключается в том, что ваш оригинал использует \ r \ n (0xODOA) в качестве новой строки, а ваш «текст в соответствии» сохраняется с помощью \ n (0x0A) .. тогда этот процесс сопоставления мертв вода ... («diff» не имеет таких проблем) ...

# In a text file, replace one block of lines with another block # # Keeping with the 'Jabberwocky' theme, # and using 'sed' with 'hexdump', so # there is no possible *special* char clash. # # The current setup will replace only the first instance. # Using sed's 'g' command, it cah change all instances. # lookinglass="$HOME/Through the Looking-Glass by Lewis Carroll" jabberwocky="$lookinglass (jabberwocky)" ykcowrebbaj="$lookinglass (ykcowrebbaj)" ##### This section if FOR TEST PREPARATION ONLY fromURL="http://www.gutenberg.org/ebooks/12.txt.utf8" wget $fromURL -O "$lookinglass" if (($?==0)) then echo "Download OK" else exit 1 fi # Make a backup of the original (while testing) cp "$lookinglass" "$lookinglass(fromURL)" # # Extact the poem and write it to a file. (It runs from line 322-359) sed -n 322,359p "$lookinglass" > "$jabberwocky" cat "$jabberwocky"; read -p "This is the original.. (press Enter to continue)" # # Make a file containing a replacement block of lines tac "$jabberwocky" > "$ykcowrebbaj" cat "$ykcowrebbaj"; read -p "This is the REPLACEMENT.. (press Enter to continue)" ##### End TEST PREPARATION # The main process # # Make 'hexdump' versions of the 3 files... source, expected, replacement cat "$lookinglass" | hexdump -v -e '1/1 "%02x"' > "$lookinglass.xdig" cat "$jabberwocky" | hexdump -v -e '1/1 "%02x"' > "$jabberwocky.xdig" cat "$ykcowrebbaj" | hexdump -v -e '1/1 "%02x"' > "$ykcowrebbaj.xdig" # Now use 'sed' in a safe (no special chrs) way. # Note, all files are now each, a single line ('\n' is now '0A') sed -i "s/$(cat "$jabberwocky.xdig")/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" ##### This section if FOR CHECKING THE RESULTS ONLY # Check result 1 read -p "About to test for the presence of 'jabberwocky.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$jabberwocky.xdig" echo -e "\n\nA dump above this line, means: 'jabberwocky' is as expected\n" # Check result 2 read -p "About to test for the presence of 'ykcowrebbaj.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$ykcowrebbaj.xdig" echo -e "\n\nA dump above this line, means: 'ykcowrebbaj' is as expected\n" # Check result 3 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" echo -e "\n\nA dump above this line, means: 'lookinglass' is as expected\n" # Check result 4 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$lookinglass.xdig" echo -e "\n\nNo dump above this line means: 'lookinglass' is as expected\n" ##### End of CHECKING THE RESULTS # Now convert the hexdump to binary, and overwrite the original cat "$lookinglass.xdig" | xxd -r -p > "$lookinglass" # Echo the "modified" poem to the screen sed -n 322,359p "$lookinglass" echo -e "\n\nYou are now looking at the REPLACEMENT text (dumped directly from the source 'book'"
2
ответ дан 25 July 2018 в 22:38
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и указать строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только "трепку" в этом весь Линукс убунту тоже уже около 4 месяцев, поэтому, когда представляешь, как это захватывает меня, оно задает цель, и это здорово для руки-на баш/общее впечатление... но, как я упоминал в комментариях где-то, есть только 7 линии эфирного кода; остальные были просто "отладка" вещи и dowloadint тестовый файл, и т. д.... (Я многое узнал от него... – Peter.O 10 January 2011 в 00:09

Подход 1: временно изменить новые строки на что-то еще

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

<old.txt tr '\n' '|' | sed 's/\(|\|^\)'\''Twas … toves|Did … Bandersnatch!'\''|/new line 1|new line 2|/g' | tr '|' '\n' >new.txt

Подход 2: изменение разделителя записей утилиты

Поддержка Awk и perl, поддерживающая два или более пустые строки в качестве разделителя записей. С awk передайте -vRS= (пустая переменная RS). С помощью Perl пройдите -000 («режим абзаца») или установите $,="". Это не полезно здесь, так как у вас есть строка поиска с несколькими пунктами.

Awk и perl также поддерживают установку любой строки в качестве разделителя записей. Установите RS или $, на любую строку, которая не находится в вашей строке поиска.

<old.txt perl -pe ' BEGIN {$, = "|"} s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

Подход 3: работа над всем файлом

Некоторые утилиты легко позволяют вам читать весь файл в память и работать над ним.

<old.txt perl -0777 -pe ' s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

Подход 4: program

Прочитайте строки один за другим. Начните с пустого буфера. Если вы видите строку «Twas» и буфер пуст, поместите ее в буфер. Если вы видите «Did gyre» и есть одна строка в буфере, добавьте текущую строку в буфер и так далее. Если вы только что добавили строку «Bandersnatch», выведите заменяющий текст. Если текущая строка не попала в буфер, напечатайте содержимое буфера, распечатайте текущую строку и очистите буфер.

psusi показывает реализацию sed. В sed концепция буфера встроена; это называется удерживающим пространством. В awk или perl вы просто используете переменную (возможно, две, одну для содержимого буфера и одну для количества строк).

3
ответ дан 26 July 2018 в 23:20
  • 1
    Жиль, спасибо за варианты. Как я уже упоминал в других комментариях, я исключила все, что использует регулярное выражение. Потому что мой поиск-текст, в какой-то момент, столкновение с регулярного выражения специальные символы.. я думала, что такое может быть хорошо известна в кодера миров (исходный код модов), а может и нет... я посмотрю на awk немного дальше, но я подозреваю, что read -r (я только что обнаружил -р сегодня) может быть путь, чтобы пойти... я написал сценарий прошлой неделе, что не будет использовать регулярные выражения, но я уже знал, где можно найти текст (по своей линии-номер). read -r или awk может работать для обнаружения в неизвестном файле. – Peter.O 9 January 2011 в 07:22
  • 2
    @Фред.медведь: поиск текста, содержащего специальные символы регулярных выражений-это отдельная тема. Один способ решить это для предобработки строку поиска процитировать специальные символы. Лучше, если программа поддерживает его, чтобы сделать символьную строку поиска. На awk: функция index. На Perl: функции index, \Q…\E обработать побег. – Gilles 9 January 2011 в 15:51
  • 3
    Gilles, инструменту нужно будет поддерживать не только литеральный поиск строк, но и буквальную замену строк. – loevborg 9 January 2011 в 21:48
  • 4
    @loevborg: В Perl это просто s/\Q$needle/$haystack/g. Awk менее прост, но выполним. – Gilles 9 January 2011 в 21:59

я был уверен, что там должен быть способ сделать это с помощью sed. После некоторых погуглив я наткнулся на это:

http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/

основан на том, что я закончил писать:

sed -n '1h;1!H;${;g;s/foo\nbar/jar\nhead/g;p;}' < x

, который правильно взял содержимое x:

Василий Пупкин

и выплюнул:

лысая голова

2
ответ дан 26 July 2018 в 23:20
  • 1
    Я не рекомендую СЭД здесь. В то время как он может сделать это, используя трюм, быстро сложная (здесь, с тремя линиями это уже бардак). – Gilles 9 January 2011 в 00:05
  • 2
    Это, безусловно, заставило меня разобраться. Я использую sed (и так далее), но, как сказал Жиль, работа с пространством удержания может быстро стать болью (поэтому я стараюсь держаться подальше от него). Однако самая большая проблема с любым поиском регулярных выражений - это когда ваш шаблон регулярного выражения & Quot; неизвестно & Quot ;; вероятность столкновения высока ... Поэтому я исключаю все, что использует regex. Главное, чтобы избежать ручной настройки ... Честно говоря, если sed имеет некоторый способ поворота off regex, то его функция address может быть очень полезной , в противном случае это не инструмент для работы .. спасибо хотя; Хорошая беседа – Peter.O 9 January 2011 в 06:26

обновление: loevborg это скрипт на языке Python-это, конечно, самое простое и лучшее решение (нет сомнений) и я очень счастлива с ним, но я хотел бы отметить, что баш скрипт я представил (в конце вопрос) не так сложно, как кажется.. я обрезал все отладки шлак, который я использовал, чтобы проверить его.. и вот он снова без вскрыши (для кого посещение этой страницы).. это в основном sed один-лайнер, С до и после наговора-преобразования :

F=("$haystack" "$needle" "$replacement") for f in "${F[@]}" ; do cat "$f" | hexdump -v -e '1/1 "%02x"' > "$f.hex" ; done sed -i "s/$(cat "${F[1])}.hex")/$(cat "${F[2])}.hex")/p" "${F[0])}.hex" cat "${F[0])}.hex" | xxd -r -p > "${F[0])}" # delete the temp *.hex files.

просто, чтобы бросить свою шляпу на ринг, я придумал решение СЭД, по которым не возникнут какие-либо проблемы с обновлением символы регулярных выражений, потому что он использует даже не одного! .. вместо этого он работает на Hexdumped версии файлов...

я думаю, что это слишком "тяжелой", но он работает, и, видимо, не ограничен каким-либо ограничений по размеру.. ГНУ СЭД имеет неограниченный узор Размер буфера, и именно там, где Hexdumped блок поиска строк заканчивается.. так что все нормально в этом отношении...

я все еще ищу шаблон решение, потому что он будет более гибким в отношении пробела (и я бы ожидать; быстрее)... но пока.. это знаменитый мистер СЭД. :)

этот скрипт полностью работает, и разумно сказала, что... она кажется больше, что это; я только 7 строк базовый код. Для полу-реалистичный тест, он скачивает книги "Алиса в Зазеркалье" из проекта "Гутенберг" (363.1 КБ) ... и заменяет оригинальный Бармаглот стихотворение со строкой-перевернутая версия.. (интересно, это не сильно отличается прочитав его задом наперед :)

ПС. Я просто поняла, что слабость в этом методе-это если оригинал использует \р\н (0xODOA), так как это символ новой строки, и свой "текст, чтобы соответствовать" сохраняется с \п (0x0A).. потом этот процесс сопоставления является мертвым в воде... ('различия' нет таких проблем) ...

# In a text file, replace one block of lines with another block # # Keeping with the 'Jabberwocky' theme, # and using 'sed' with 'hexdump', so # there is no possible *special* char clash. # # The current setup will replace only the first instance. # Using sed's 'g' command, it cah change all instances. # lookinglass="$HOME/Through the Looking-Glass by Lewis Carroll" jabberwocky="$lookinglass (jabberwocky)" ykcowrebbaj="$lookinglass (ykcowrebbaj)" ##### This section if FOR TEST PREPARATION ONLY fromURL="http://www.gutenberg.org/ebooks/12.txt.utf8" wget $fromURL -O "$lookinglass" if (($?==0)) then echo "Download OK" else exit 1 fi # Make a backup of the original (while testing) cp "$lookinglass" "$lookinglass(fromURL)" # # Extact the poem and write it to a file. (It runs from line 322-359) sed -n 322,359p "$lookinglass" > "$jabberwocky" cat "$jabberwocky"; read -p "This is the original.. (press Enter to continue)" # # Make a file containing a replacement block of lines tac "$jabberwocky" > "$ykcowrebbaj" cat "$ykcowrebbaj"; read -p "This is the REPLACEMENT.. (press Enter to continue)" ##### End TEST PREPARATION # The main process # # Make 'hexdump' versions of the 3 files... source, expected, replacement cat "$lookinglass" | hexdump -v -e '1/1 "%02x"' > "$lookinglass.xdig" cat "$jabberwocky" | hexdump -v -e '1/1 "%02x"' > "$jabberwocky.xdig" cat "$ykcowrebbaj" | hexdump -v -e '1/1 "%02x"' > "$ykcowrebbaj.xdig" # Now use 'sed' in a safe (no special chrs) way. # Note, all files are now each, a single line ('\n' is now '0A') sed -i "s/$(cat "$jabberwocky.xdig")/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" ##### This section if FOR CHECKING THE RESULTS ONLY # Check result 1 read -p "About to test for the presence of 'jabberwocky.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$jabberwocky.xdig" echo -e "\n\nA dump above this line, means: 'jabberwocky' is as expected\n" # Check result 2 read -p "About to test for the presence of 'ykcowrebbaj.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$ykcowrebbaj.xdig" echo -e "\n\nA dump above this line, means: 'ykcowrebbaj' is as expected\n" # Check result 3 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" echo -e "\n\nA dump above this line, means: 'lookinglass' is as expected\n" # Check result 4 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$lookinglass.xdig" echo -e "\n\nNo dump above this line means: 'lookinglass' is as expected\n" ##### End of CHECKING THE RESULTS # Now convert the hexdump to binary, and overwrite the original cat "$lookinglass.xdig" | xxd -r -p > "$lookinglass" # Echo the "modified" poem to the screen sed -n 322,359p "$lookinglass" echo -e "\n\nYou are now looking at the REPLACEMENT text (dumped directly from the source 'book'"
2
ответ дан 26 July 2018 в 23:20
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и цитаты в строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только «трепетал». в течение всего этого времени Linux Ubuntu в течение примерно 4 месяцев, поэтому, когда такая идея захватывает меня, она устанавливает цель, и это отлично подходит для получения серьезного ручного решения для bash / general experiance ... но, как я упоминаю в комментариях где-то существует только 7 строк эссенциального кода; остальное - это просто «отладка». материал и dowloadint тестовый файл и т. д. (я многому научился у него ... – Peter.O 10 January 2011 в 00:09

подход 1: временно изменить строки в нечто другое

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

<old.txt tr '\n' '|' | sed 's/\(|\|^\)'\''Twas … toves|Did … Bandersnatch!'\''|/new line 1|new line 2|/g' | tr '|' '\n' >new.txt

подход 2: смените пластинку сепаратора утилиты

поддержка на awk и Perl установка двух или более пустые строки как разделитель записей. С awk, пройти -vRS= (пустой RS переменная). С Perl, пройти -000 (“пункт режим”) или установите для параметра $,="". Это не полезно, вот хоть у тебя есть мульти-пункт строку поиска.

на awk и Perl также поддерживает установку любой строки как разделитель записей. Установить нажать [F8] и [F9] и любую строку, а не в строку поиска.

<old.txt perl -pe ' BEGIN {$, = "|"} s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

подход 3: Работа на весь файл

некоторые утилиты позволят вам легко считывать весь файл в память и работать на нем.

<old.txt perl -0777 -pe ' s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

подход 4: программы

читать по одной линии. Начинать с пустого буфера. Если вы видите “линия тва” и буфер пуст, поместить его в буфер. Если вы видите “сделал круговращение” и там одна строка в буфер, добавить текущую строку в буфер, и так далее. Если вы только что добавленный строке “Брандашмыг”, вывод текста замены. Если текущая строка не идут в буфер, распечатать содержимое буфера, печать текущую строку и пустой буфер.

psusi показывает внедрение СЭД. В СЭД, буфер концепция встроенные; это называется трюм. В awk или Perl, вы бы просто использовать переменную (возможно два, один за содержимое буфера и один для нескольких строк).

3
ответ дан 31 July 2018 в 11:11
  • 1
    Жиль, спасибо за варианты. Как я уже упоминал в других комментариях, я исключила все, что использует регулярное выражение. Потому что мой поиск-текст, в какой-то момент, столкновение с регулярного выражения специальные символы.. я думала, что такое может быть хорошо известна в кодера миров (исходный код модов), а может и нет... я посмотрю на awk немного дальше, но я подозреваю, что read -r (я только что обнаружил -р сегодня) может быть путь, чтобы пойти... я написал сценарий прошлой неделе, что не будет использовать регулярные выражения, но я уже знал, где можно найти текст (по своей линии-номер). read -r или awk может работать для обнаружения в неизвестном файле. – Peter.O 9 January 2011 в 07:22
  • 2
    @ fred.bear: поиск текста, содержащего специальные символы регулярного выражения, является отдельной проблемой. Один из способов его решения - препроцитировать строку поиска, чтобы указать специальные символы. Лучший способ, если утилита поддерживает его, - выполнить строчный поиск по строкам. Awk: index. Perl: функция index, \Q…\E escape-выход. – Gilles 9 January 2011 в 15:51
  • 3
    Gilles, инструменту нужно будет поддерживать не только литеральный поиск строк, но и буквальную замену строк. – loevborg 9 January 2011 в 21:48
  • 4
    @loevborg: в Perl, это просто s/\Q$needle/$haystack/g. Awk-это менее очевидно, но выполнимо. – Gilles 9 January 2011 в 21:59

Я был уверен, что должен был быть способ сделать это с sed. После некоторого googling я наткнулся на это:

http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/

Основано на что я закончил писать:

sed -n '1h;1!H;${;g;s/foo\nbar/jar\nhead/g;p;}' < x

Что правильно взяло содержимое x:

foo bar

И выплюнуть :

jar head

2
ответ дан 31 July 2018 в 11:11
  • 1
    Я бы не стал рекомендовать sed здесь. Хотя он может это сделать, использование пространства удержания быстро усложняется (здесь, с тремя линиями, это уже беспорядок). – Gilles 9 January 2011 в 00:05
  • 2
    Это, безусловно, меня thingking. Я использую СЭД (и нравится), но как Жиль отметил, работая с Свободное место может быстро стать болью (поэтому я стараюсь держаться подальше от него).. но самая большая проблема с regex поиск, это когда Ваше регулярное выражение картины "неизвестная"; вероятность столкновения высока... так что я исключаю все, что использует регулярное выражение. Главное в этом, чтобы избежать ручной настройки... честно говоря, если ООО имеет несколько способов превращения от регулярное выражение, то его диапазон адресов[!характеристика Д1] может быть очень полезным, иначе это не инструмент для работы.. спасибо; СЭД говорить хорошо говорить – Peter.O 9 January 2011 в 06:26

UPDATE: скрипт python от loevborg, безусловно, является самым простым и лучшим решением (в этом нет никаких сомнений), и я очень доволен этим, но я хотел бы указать, что сценарий bash, который я представил (в конце вопрос) нигде не так сложно, как кажется. Я урезал всю отладочную ветвь, которую я использовал для ее проверки .. и здесь она снова не имеет перегруженности (для тех, кто посещает эту страницу). Это в основном sed однострочный с предварительным и пост-шестнадцатеричным преобразованиями:

F=("$haystack" "$needle" "$replacement") for f in "${F[@]}" ; do cat "$f" | hexdump -v -e '1/1 "%02x"' > "$f.hex" ; done sed -i "s/$(cat "${F[1])}.hex")/$(cat "${F[2])}.hex")/p" "${F[0])}.hex" cat "${F[0])}.hex" | xxd -r -p > "${F[0])}" # delete the temp *.hex files.

Просто, чтобы бросить шляпу в кольцо, я придумал решение «sed» который не столкнется с проблемами с UPDATE символами регулярных выражений, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

Я думаю, что он слишком «тяжелый», но он работает и, по-видимому, не ограничен ограничениями на размер. GNU sed имеет неограниченный размер буфера шаблонов, и вот где заканчивается блок строк поиска Hexdumped. Так что в этом отношении все в порядке ...

Я все еще ищу шаблон потому что он будет более гибким в отношении белого пространства (и я бы ожидал, быстрее) ... но до этого .. Это знаменитый мистер Сед. :)

Этот скрипт полностью запущен как есть, и разумно прокомментирован ... Он выглядит больше, чем он есть; У меня всего 7 строк кода. Для полуреалистичного теста он загружает книгу «Алиса через зазеркалье» из Project Gutenberg (363.1 KB) ... и заменяет оригинальное стихотворение Jabberwocky собственной версией строки .. (Интересно, что это не так много другое чтение его назад :)

PS. Я просто понял, что слабость в этом методе заключается в том, что ваш оригинал использует \ r \ n (0xODOA) в качестве новой строки, а ваш «текст в соответствии» сохраняется с помощью \ n (0x0A) .. тогда этот процесс сопоставления мертв вода ... («diff» не имеет таких проблем) ...

# In a text file, replace one block of lines with another block # # Keeping with the 'Jabberwocky' theme, # and using 'sed' with 'hexdump', so # there is no possible *special* char clash. # # The current setup will replace only the first instance. # Using sed's 'g' command, it cah change all instances. # lookinglass="$HOME/Through the Looking-Glass by Lewis Carroll" jabberwocky="$lookinglass (jabberwocky)" ykcowrebbaj="$lookinglass (ykcowrebbaj)" ##### This section if FOR TEST PREPARATION ONLY fromURL="http://www.gutenberg.org/ebooks/12.txt.utf8" wget $fromURL -O "$lookinglass" if (($?==0)) then echo "Download OK" else exit 1 fi # Make a backup of the original (while testing) cp "$lookinglass" "$lookinglass(fromURL)" # # Extact the poem and write it to a file. (It runs from line 322-359) sed -n 322,359p "$lookinglass" > "$jabberwocky" cat "$jabberwocky"; read -p "This is the original.. (press Enter to continue)" # # Make a file containing a replacement block of lines tac "$jabberwocky" > "$ykcowrebbaj" cat "$ykcowrebbaj"; read -p "This is the REPLACEMENT.. (press Enter to continue)" ##### End TEST PREPARATION # The main process # # Make 'hexdump' versions of the 3 files... source, expected, replacement cat "$lookinglass" | hexdump -v -e '1/1 "%02x"' > "$lookinglass.xdig" cat "$jabberwocky" | hexdump -v -e '1/1 "%02x"' > "$jabberwocky.xdig" cat "$ykcowrebbaj" | hexdump -v -e '1/1 "%02x"' > "$ykcowrebbaj.xdig" # Now use 'sed' in a safe (no special chrs) way. # Note, all files are now each, a single line ('\n' is now '0A') sed -i "s/$(cat "$jabberwocky.xdig")/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" ##### This section if FOR CHECKING THE RESULTS ONLY # Check result 1 read -p "About to test for the presence of 'jabberwocky.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$jabberwocky.xdig" echo -e "\n\nA dump above this line, means: 'jabberwocky' is as expected\n" # Check result 2 read -p "About to test for the presence of 'ykcowrebbaj.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$ykcowrebbaj.xdig" echo -e "\n\nA dump above this line, means: 'ykcowrebbaj' is as expected\n" # Check result 3 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" echo -e "\n\nA dump above this line, means: 'lookinglass' is as expected\n" # Check result 4 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$lookinglass.xdig" echo -e "\n\nNo dump above this line means: 'lookinglass' is as expected\n" ##### End of CHECKING THE RESULTS # Now convert the hexdump to binary, and overwrite the original cat "$lookinglass.xdig" | xxd -r -p > "$lookinglass" # Echo the "modified" poem to the screen sed -n 322,359p "$lookinglass" echo -e "\n\nYou are now looking at the REPLACEMENT text (dumped directly from the source 'book'"
2
ответ дан 31 July 2018 в 11:11
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и цитаты в строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только "трепку" в этом весь Линукс убунту тоже уже около 4 месяцев, поэтому, когда представляешь, как это захватывает меня, оно задает цель, и это здорово для руки-на баш/общее впечатление... но, как я упоминал в комментариях где-то, есть только 7 линии эфирного кода; остальные были просто "отладка" вещи и dowloadint тестовый файл, и т. д.... (Я многое узнал от него... – Peter.O 10 January 2011 в 00:09

Подход 1: временно изменить новые строки на что-то еще

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

<old.txt tr '\n' '|' | sed 's/\(|\|^\)'\''Twas … toves|Did … Bandersnatch!'\''|/new line 1|new line 2|/g' | tr '|' '\n' >new.txt

Подход 2: изменение разделителя записей утилиты

Поддержка Awk и perl, поддерживающая два или более пустые строки в качестве разделителя записей. С awk передайте -vRS= (пустая переменная RS). С помощью Perl пройдите -000 («режим абзаца») или установите $,="". Это не полезно здесь, так как у вас есть строка поиска с несколькими пунктами.

Awk и perl также поддерживают установку любой строки в качестве разделителя записей. Установите RS или $, на любую строку, которая не находится в вашей строке поиска.

<old.txt perl -pe ' BEGIN {$, = "|"} s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

Подход 3: работа над всем файлом

Некоторые утилиты легко позволяют вам читать весь файл в память и работать над ним.

<old.txt perl -0777 -pe ' s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

Подход 4: program

Прочитайте строки один за другим. Начните с пустого буфера. Если вы видите строку «Twas» и буфер пуст, поместите ее в буфер. Если вы видите «Did gyre» и есть одна строка в буфере, добавьте текущую строку в буфер и так далее. Если вы только что добавили строку «Bandersnatch», выведите заменяющий текст. Если текущая строка не попала в буфер, напечатайте содержимое буфера, распечатайте текущую строку и очистите буфер.

psusi показывает реализацию sed. В sed концепция буфера встроена; это называется удерживающим пространством. В awk или perl вы просто используете переменную (возможно, две, одну для содержимого буфера и одну для количества строк).

3
ответ дан 31 July 2018 в 12:09
  • 1
    Жиль, спасибо за варианты. Как я уже упоминал в других комментариях, я исключил все, что использует регулярное выражение. Потому что мой текст поиска в какой-то момент столкнется с специальными символами регулярных выражений .. Я думал, что что-то вроде этого может быть хорошо известно в царствах кодера (исходные коды), но, возможно, нет ... Я рассмотрю awk немного позже, но я подозреваю, что read -r (я только что открыл -r сегодня) может быть способом ... Я написал рабочий скрипт на прошлой неделе, который не использует регулярное выражение, но я уже знал, где найти текст (через его номер строки). read -r или awk могут работать для поиска в неизвестном файле. – Peter.O 9 January 2011 в 07:22
  • 2
    @Фред.медведь: поиск текста, содержащего специальные символы регулярных выражений-это отдельная тема. Один способ решить это для предобработки строку поиска процитировать специальные символы. Лучше, если программа поддерживает его, чтобы сделать символьную строку поиска. На awk: функция index. На Perl: функции index, \Q…\E обработать побег. – Gilles 9 January 2011 в 15:51
  • 3
    Gilles, инструменту нужно будет поддерживать не только литеральный поиск строк, но и буквальную замену строк. – loevborg 9 January 2011 в 21:48
  • 4
    @loevborg: в Perl, это просто s/\Q$needle/$haystack/g. Awk-это менее очевидно, но выполнимо. – Gilles 9 January 2011 в 21:59

я был уверен, что там должен быть способ сделать это с помощью sed. После некоторых погуглив я наткнулся на это:

http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/

основан на том, что я закончил писать:

sed -n '1h;1!H;${;g;s/foo\nbar/jar\nhead/g;p;}' < x

, который правильно взял содержимое x:

Василий Пупкин

и выплюнул:

лысая голова

2
ответ дан 31 July 2018 в 12:09
  • 1
    Я не рекомендую СЭД здесь. В то время как он может сделать это, используя трюм, быстро сложная (здесь, с тремя линиями это уже бардак). – Gilles 9 January 2011 в 00:05
  • 2
    Это, безусловно, заставило меня разобраться. Я использую sed (и так далее), но, как сказал Жиль, работа с пространством удержания может быстро стать болью (поэтому я стараюсь держаться подальше от него). Однако самая большая проблема с любым поиском регулярных выражений - это когда ваш шаблон регулярного выражения & Quot; неизвестно & Quot ;; вероятность столкновения высока ... Поэтому я исключаю все, что использует regex. Главное, чтобы избежать ручной настройки ... Честно говоря, если sed имеет некоторый способ поворота off regex, то его функция address может быть очень полезной , в противном случае это не инструмент для работы .. спасибо хотя; Хорошая беседа – Peter.O 9 January 2011 в 06:26

даже если Вы не любите седой [F2] и perl, вы можете по-прежнему найти вкус в серой-templed awk. Этот ответ, кажется, то, что вы ищете. Я воспроизвожу его здесь. Скажем, у вас есть три файла и хотите заменить needle с replacement в haystack:

awk ' BEGIN { RS="" } FILENAME==ARGV[1] { s=$0 } FILENAME==ARGV[2] { r=$0 } FILENAME==ARGV[3] { sub(s,r) ; print } ' needle replacement haystack > output

это не связано с регулярными выражениями и поддерживает символы новой строки. Это похоже на работу с достаточно большими файлами. Оно связано чавкать весь файл в память, поэтому он не будет работать с файлами произвольного размера. Если вы хотите его более элегантным, вы можете приложить всю эту историю в bash-скрипт, или превратить его в awk скрипт.

2
ответ дан 31 July 2018 в 12:09
  • 1
    Я, должно быть, дал неправильное сообщение. Я LOVE 'sed'! и использовать его для всех вещей под солнцем ... Я просто думаю, что это не лучший инструмент для этой работы .... Я собираюсь опубликовать решение «sed», которое работает, и НЕ будет проблемы с вызовом специальных символов регулярных выражений, но я чувствую, что он создает слишком много файлов и поэтому является «тяжелым». для работы ...... После того, как я разместил его и сделал перерыв, я хорошо рассмотрю ваше решение. Спасибо ... – Peter.O 9 January 2011 в 17:37
  • 2
    .. К сожалению, по отношению к специальным символам регулярного выражения, если они не совпадают, а также все регулярные выражения. Когда они сталкиваются с специальным символом , они обрабатывают его особым образом. Нехорошо, когда не предназначен для специальных. Он разбился на [, ( и ложные результаты на $, ^ (не нашел данных, хотя он был идентичным) ... Я не проверял дальше ... (Но команда выглядит «правильно». :) – Peter.O 9 January 2011 в 20:56
  • 3
    Фред, ты прав; я должен был проверить документацию. Кроме того gsub представляется более целесообразным, чем sub. Я нахожу это довольно странно, что нет простой mulitline поиск nonregex/замене инженерных подвернулся. Там, кажется, нет простого способа вокруг побега/Цитировать поиск иглы (в perl, используя quotemeta например). – loevborg 9 January 2011 в 21:43
  • 4
    Я просто осознайте grep -F --fixed-strings . Что ставит команды grep в совершенно новой категории (для меня) ... как read -r... буквальное толкование.. если только sed было это, было бы все очень просто.. (возможно [F4] и есть что-то вроде этого(?) .... и кстати. самый простой частью всего этого является замена линий; простой голову (один раз в первой строке-число выявленных) | замена КПП |хвост остальное (длина удален кусок известно)... так что теперь, с grep -F -A{num} это может быть только зашили :) – Peter.O 9 January 2011 в 22:26

UPDATE: скрипт python от loevborg, безусловно, является самым простым и лучшим решением (в этом нет никаких сомнений), и я очень доволен этим, но я хотел бы указать, что сценарий bash, который я представил (в конце вопрос) нигде не так сложно, как кажется. Я урезал всю отладочную ветвь, которую я использовал для ее проверки .. и здесь она снова не имеет перегруженности (для тех, кто посещает эту страницу). Это в основном sed однострочный с предварительным и пост-шестнадцатеричным преобразованиями:

F=("$haystack" "$needle" "$replacement") for f in "${F[@]}" ; do cat "$f" | hexdump -v -e '1/1 "%02x"' > "$f.hex" ; done sed -i "s/$(cat "${F[1])}.hex")/$(cat "${F[2])}.hex")/p" "${F[0])}.hex" cat "${F[0])}.hex" | xxd -r -p > "${F[0])}" # delete the temp *.hex files.

Просто, чтобы бросить шляпу в кольцо, я придумал решение «sed» который не столкнется с проблемами с UPDATE символами регулярных выражений, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

Я думаю, что он слишком «тяжелый», но он работает и, по-видимому, не ограничен ограничениями на размер. GNU sed имеет неограниченный размер буфера шаблонов, и вот где заканчивается блок строк поиска Hexdumped. Так что в этом отношении все в порядке ...

Я все еще ищу шаблон потому что он будет более гибким в отношении белого пространства (и я бы ожидал, быстрее) ... но до этого .. Это знаменитый мистер Сед. :)

Этот скрипт полностью запущен как есть, и разумно прокомментирован ... Он выглядит больше, чем он есть; У меня всего 7 строк кода. Для полуреалистичного теста он загружает книгу «Алиса через зазеркалье» из Project Gutenberg (363.1 KB) ... и заменяет оригинальное стихотворение Jabberwocky собственной версией строки .. (Интересно, что это не так много другое чтение его назад :)

PS. Я просто понял, что слабость в этом методе заключается в том, что ваш оригинал использует \ r \ n (0xODOA) в качестве новой строки, а ваш «текст в соответствии» сохраняется с помощью \ n (0x0A) .. тогда этот процесс сопоставления мертв вода ... («diff» не имеет таких проблем) ...

# In a text file, replace one block of lines with another block # # Keeping with the 'Jabberwocky' theme, # and using 'sed' with 'hexdump', so # there is no possible *special* char clash. # # The current setup will replace only the first instance. # Using sed's 'g' command, it cah change all instances. # lookinglass="$HOME/Through the Looking-Glass by Lewis Carroll" jabberwocky="$lookinglass (jabberwocky)" ykcowrebbaj="$lookinglass (ykcowrebbaj)" ##### This section if FOR TEST PREPARATION ONLY fromURL="http://www.gutenberg.org/ebooks/12.txt.utf8" wget $fromURL -O "$lookinglass" if (($?==0)) then echo "Download OK" else exit 1 fi # Make a backup of the original (while testing) cp "$lookinglass" "$lookinglass(fromURL)" # # Extact the poem and write it to a file. (It runs from line 322-359) sed -n 322,359p "$lookinglass" > "$jabberwocky" cat "$jabberwocky"; read -p "This is the original.. (press Enter to continue)" # # Make a file containing a replacement block of lines tac "$jabberwocky" > "$ykcowrebbaj" cat "$ykcowrebbaj"; read -p "This is the REPLACEMENT.. (press Enter to continue)" ##### End TEST PREPARATION # The main process # # Make 'hexdump' versions of the 3 files... source, expected, replacement cat "$lookinglass" | hexdump -v -e '1/1 "%02x"' > "$lookinglass.xdig" cat "$jabberwocky" | hexdump -v -e '1/1 "%02x"' > "$jabberwocky.xdig" cat "$ykcowrebbaj" | hexdump -v -e '1/1 "%02x"' > "$ykcowrebbaj.xdig" # Now use 'sed' in a safe (no special chrs) way. # Note, all files are now each, a single line ('\n' is now '0A') sed -i "s/$(cat "$jabberwocky.xdig")/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" ##### This section if FOR CHECKING THE RESULTS ONLY # Check result 1 read -p "About to test for the presence of 'jabberwocky.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$jabberwocky.xdig" echo -e "\n\nA dump above this line, means: 'jabberwocky' is as expected\n" # Check result 2 read -p "About to test for the presence of 'ykcowrebbaj.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$ykcowrebbaj.xdig" echo -e "\n\nA dump above this line, means: 'ykcowrebbaj' is as expected\n" # Check result 3 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$ykcowrebbaj.xdig")/p" "$lookinglass.xdig" echo -e "\n\nA dump above this line, means: 'lookinglass' is as expected\n" # Check result 4 read -p "About to test for the presence of 'lookinglass.xdig' within itself (Enter) " sed -n "/$(cat "$jabberwocky.xdig")/p" "$lookinglass.xdig" echo -e "\n\nNo dump above this line means: 'lookinglass' is as expected\n" ##### End of CHECKING THE RESULTS # Now convert the hexdump to binary, and overwrite the original cat "$lookinglass.xdig" | xxd -r -p > "$lookinglass" # Echo the "modified" poem to the screen sed -n 322,359p "$lookinglass" echo -e "\n\nYou are now looking at the REPLACEMENT text (dumped directly from the source 'book'"
2
ответ дан 31 July 2018 в 12:09
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и указать строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только «трепетал». в течение всего этого времени Linux Ubuntu в течение примерно 4 месяцев, поэтому, когда такая идея захватывает меня, она устанавливает цель, и это отлично подходит для получения серьезного ручного решения для bash / general experiance ... но, как я упоминаю в комментариях где-то существует только 7 строк эссенциального кода; остальное - это просто «отладка». материал и dowloadint тестовый файл и т. д. (я многому научился у него ... – Peter.O 10 January 2011 в 00:09

Подход 1: временно изменить новые строки на что-то еще

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

<old.txt tr '\n' '|' | sed 's/\(|\|^\)'\''Twas … toves|Did … Bandersnatch!'\''|/new line 1|new line 2|/g' | tr '|' '\n' >new.txt

Подход 2: изменение разделителя записей утилиты

Поддержка Awk и perl, поддерживающая два или более пустые строки в качестве разделителя записей. С awk передайте -vRS= (пустая переменная RS). С помощью Perl пройдите -000 («режим абзаца») или установите $,="". Это не полезно здесь, так как у вас есть строка поиска с несколькими пунктами.

Awk и perl также поддерживают установку любой строки в качестве разделителя записей. Установите RS или $, на любую строку, которая не находится в вашей строке поиска.

<old.txt perl -pe ' BEGIN {$, = "|"} s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

Подход 3: работа над всем файлом

Некоторые утилиты легко позволяют вам читать весь файл в память и работать над ним.

<old.txt perl -0777 -pe ' s/^'\''Twas … toves\nDid … Bandersnatch!'\''$/new line 1\nnew line 2/mg ' >new.txt

Подход 4: program

Прочитайте строки один за другим. Начните с пустого буфера. Если вы видите строку «Twas» и буфер пуст, поместите ее в буфер. Если вы видите «Did gyre» и есть одна строка в буфере, добавьте текущую строку в буфер и так далее. Если вы только что добавили строку «Bandersnatch», выведите заменяющий текст. Если текущая строка не попала в буфер, напечатайте содержимое буфера, распечатайте текущую строку и очистите буфер.

psusi показывает реализацию sed. В sed концепция буфера встроена; это называется удерживающим пространством. В awk или perl вы просто используете переменную (возможно, две, одну для содержимого буфера и одну для количества строк).

3
ответ дан 2 August 2018 в 04:05
  • 1
    Жиль, спасибо за варианты. Как я уже упоминал в других комментариях, я исключил все, что использует регулярное выражение. Потому что мой текст поиска в какой-то момент столкнется с специальными символами регулярных выражений .. Я подумал, что что-то вроде этого может быть хорошо известно в царствах кодера (исходные коды), но, возможно, нет ... Я рассмотрю awk немного позже, но я подозреваю, что read -r (я только что открыл -r сегодня) может быть способом ... Я написал рабочий скрипт на прошлой неделе, который не использует регулярное выражение, но я уже знал, где найти текст (через его номер строки). read -r или awk могут работать для поиска в неизвестном файле. – Peter.O 9 January 2011 в 07:22
  • 2
    @ fred.bear: поиск текста, содержащего специальные символы регулярного выражения, является отдельной проблемой. Один из способов его решения - препроцитировать строку поиска, чтобы указать специальные символы. Лучший способ, если утилита поддерживает его, - выполнить строчный поиск по строкам. Awk: index. Perl: функция index, \Q…\E escape-выход. – Gilles 9 January 2011 в 15:51
  • 3
    Жиль, инструмент необходимо поддерживать не только буквальное строке поиска, а также символьную строку замещения. – loevborg 9 January 2011 в 21:48
  • 4
    @loevborg: в Perl, это просто s/\Q$needle/$haystack/g. Awk-это менее очевидно, но выполнимо. – Gilles 9 January 2011 в 21:59

Другие вопросы по тегам:

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