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

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

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

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

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

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

48 ответов

Я был уверен, что должен был быть способ сделать это с 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
ответ дан 2 August 2018 в 04:05
  • 1
    Я не рекомендую СЭД здесь. В то время как он может сделать это, используя трюм, быстро сложная (здесь, с тремя линиями это уже бардак). – Gilles 9 January 2011 в 00:05
  • 2
    Это, безусловно, заставило меня разобраться. Я использую sed (и так далее), но, как сказал Жиль, работа с пространством удержания может быстро стать болью (поэтому я стараюсь держаться подальше от него). Однако самая большая проблема с любым поиском регулярных выражений - это когда ваш шаблон регулярного выражения & Quot; неизвестно & Quot ;; вероятность столкновения высока ... Поэтому я исключаю все, что использует regex. Главное, чтобы избежать ручной настройки ... Честно говоря, если sed имеет некоторый способ поворота off regex, то его функция address может быть очень полезной , в противном случае это не инструмент для работы .. спасибо хотя; Хорошая беседа – 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
ответ дан 2 August 2018 в 04:05
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и цитаты в строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только «трепетал». в течение всего этого времени Linux Ubuntu в течение примерно 4 месяцев, поэтому, когда такая идея захватывает меня, она устанавливает цель, и это отлично подходит для получения серьезного ручного решения для bash / general experiance ... но, как я упоминаю в комментариях где-то существует только 7 строк эссенциального кода; остальное - это просто «отладка». материал и dowloadint тестовый файл и т. д. (я многому научился у него ... – Peter.O 10 January 2011 в 00:09

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

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», которое не будет сталкиваются с любыми проблемами со специальными регулярными выражениями, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

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

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

Этот скрипт полностью запущен как есть, и он прокомментирован ... Он выглядит больше, чем он есть; У меня всего 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
ответ дан 4 August 2018 в 20:08

Я был уверен, что должен был быть способ сделать это с 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;} '& lt; x

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

foo bar

И выплюнул:

jar head [ ! d9]

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

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

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

  & lt; old.txt tr '\n' '|'  |  sed 's / \ (| \ | ^ \)' \ '' Twas ... toves | Did ... Bandersnatch! '\' '| / новая строка 1 | новая строка 2 | / g' |  tr '|'  '\n' & gt; new.txt  

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

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

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

  & lt; old.txt perl -pe 'BEGIN  {$, = "|"} s / ^ '\' 'Twas ... toves \nDid ... Bandersnatch!' \ '' $ / новая строка 1 \nnew line 2 / mg '& gt; new.txt  

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

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

  & lt; old.  txt perl -0777 -pe 's / ^' \ '' Twas ... toves \nDid ... Bandersnatch! '\' '$ / новая строка 1 \nnew line 2 / mg' & gt; new.txt  

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

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

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

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

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

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», которое не будет сталкиваются с любыми проблемами со специальными регулярными выражениями, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

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

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

Этот скрипт полностью запущен как есть, и он прокомментирован ... Он выглядит больше, чем он есть; У меня всего 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
ответ дан 6 August 2018 в 04:10

Я был уверен, что должен был быть способ сделать это с 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;} '& lt; x

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

foo bar

И выплюнул:

jar head [ ! d9]

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

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

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

  & lt; old.txt tr '\n' '|'  |  sed 's / \ (| \ | ^ \)' \ '' Twas ... toves | Did ... Bandersnatch! '\' '| / новая строка 1 | новая строка 2 | / g' |  tr '|'  '\n' & gt; new.txt  

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

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

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

  & lt; old.txt perl -pe 'BEGIN  {$, = "|"} s / ^ '\' 'Twas ... toves \nDid ... Bandersnatch!' \ '' $ / новая строка 1 \nnew line 2 / mg '& gt; new.txt  

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

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

  & lt; old.  txt perl -0777 -pe 's / ^' \ '' Twas ... toves \nDid ... Bandersnatch! '\' '$ / новая строка 1 \nnew line 2 / mg' & gt; new.txt  

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

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

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

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

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

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», которое не будет сталкиваются с любыми проблемами со специальными регулярными выражениями, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

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

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

Этот скрипт полностью запущен как есть, и он прокомментирован ... Он выглядит больше, чем он есть; У меня всего 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
ответ дан 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 .

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

Я был уверен, что должен был быть способ сделать это с 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;} '& lt; x

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

foo bar

И выплюнул:

jar head [ ! d9]

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

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

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

  & lt; old.txt tr '\n' '|'  |  sed 's / \ (| \ | ^ \)' \ '' Twas ... toves | Did ... Bandersnatch! '\' '| / новая строка 1 | новая строка 2 | / g' |  tr '|'  '\n' & gt; new.txt  

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

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

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

  & lt; old.txt perl -pe 'BEGIN  {$, = "|"} s / ^ '\' 'Twas ... toves \nDid ... Bandersnatch!' \ '' $ / новая строка 1 \nnew line 2 / mg '& gt; new.txt  

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

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

  & lt; old.  txt perl -0777 -pe 's / ^' \ '' Twas ... toves \nDid ... Bandersnatch! '\' '$ / новая строка 1 \nnew line 2 / mg' & gt; new.txt  

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

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

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

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

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

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», которое не будет сталкиваются с любыми проблемами со специальными регулярными выражениями, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

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

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

Этот скрипт полностью запущен как есть, и он прокомментирован ... Он выглядит больше, чем он есть; У меня всего 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
ответ дан 10 August 2018 в 10:23

Я был уверен, что должен был быть способ сделать это с 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;} '& lt; x

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

foo bar

И выплюнул:

jar head [ ! d9]

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

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

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

  & lt; old.txt tr '\n' '|'  |  sed 's / \ (| \ | ^ \)' \ '' Twas ... toves | Did ... Bandersnatch! '\' '| / новая строка 1 | новая строка 2 | / g' |  tr '|'  '\n' & gt; new.txt  

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

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

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

  & lt; old.txt perl -pe 'BEGIN  {$, = "|"} s / ^ '\' 'Twas ... toves \nDid ... Bandersnatch!' \ '' $ / новая строка 1 \nnew line 2 / mg '& gt; new.txt  

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

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

  & lt; old.  txt perl -0777 -pe 's / ^' \ '' Twas ... toves \nDid ... Bandersnatch! '\' '$ / новая строка 1 \nnew line 2 / mg' & gt; new.txt  

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

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

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

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

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

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», которое не будет сталкиваются с любыми проблемами со специальными регулярными выражениями, потому что он использует не один! .. вместо этого он работает с Hexdumped версиями файлов ...

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

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

Этот скрипт полностью запущен как есть, и он прокомментирован ... Он выглядит больше, чем он есть; У меня всего 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
ответ дан 13 August 2018 в 16:48
  • 1
    Это кажется невероятно трудным решением. Гораздо лучше использовать регулярные выражения и указать строку поиска. – loevborg 9 January 2011 в 21:46
  • 2
    :) ... Да, я согласен, но я только «трепетал». в течение всего этого времени Linux Ubuntu в течение примерно 4 месяцев, поэтому, когда такая идея захватывает меня, она устанавливает цель, и это отлично подходит для получения серьезного ручного решения для bash / general experiance ... но, как я упоминаю в комментариях где-то существует только 7 строк эссенциального кода; остальное - это просто «отладка». материал и dowloadint тестовый файл и т. д. (я многому научился у него ... – Peter.O 10 January 2011 в 00:09

Я был уверен, что должен был быть способ сделать это с 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;} '& lt; x

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

foo bar

И выплюнул:

jar head [ ! d9]

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

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

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

  & lt; old.txt tr '\n' '|'  |  sed 's / \ (| \ | ^ \)' \ '' Twas ... toves | Did ... Bandersnatch! '\' '| / новая строка 1 | новая строка 2 | / g' |  tr '|'  '\n' & gt; new.txt  

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

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

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

  & lt; old.txt perl -pe 'BEGIN  {$, = "|"} s / ^ '\' 'Twas ... toves \nDid ... Bandersnatch!' \ '' $ / новая строка 1 \nnew line 2 / mg '& gt; new.txt  

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

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

  & lt; old.  txt perl -0777 -pe 's / ^' \ '' Twas ... toves \nDid ... Bandersnatch! '\' '$ / новая строка 1 \nnew line 2 / mg' & gt; new.txt  

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

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

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

3
ответ дан 13 August 2018 в 16:48
  • 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

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

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