Как я могу изменить код ^ L во многих файлах в Ubuntu?


8

У меня много XML-файлов, более 50000 из них.

В некоторых файлах XML некоторые файлы пишутся так

<filename>abc.JPEG<^Lilename>

^Lэто всего лишь один символ, но я не могу найти, что ^Lзначит с Google.

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

<filename>abc.JPEG<
                   ilename>

Во всяком случае, я хочу изменить <filename>abc.JPEG<^Lilename>на<filename>abc.JPEG</filename>

Я уже нашел какую-то команду, чтобы изменить слово во многих файлах, таких как

find . -exec perl -pi -e 's/[find_word]/[change_word]/g' {} \;

Но эта команда не работает в моем случае, потому что она не может распознать искомое слово, когда я просто набираю ^L.

Как я могу изменить , <filename>abc.JPEG<^Lilename>чтобы <filename>abc.JPEG</filename>во многих файлах?


6
Видимо, кто-то использовал <\filename>вместо того, чтобы </filename>в контексте, где \fбудет интерпретироваться как символ подачи формы. Вам, вероятно, следует отследить источник этих файлов и указать разработчику на проблему с их инструментом генерации. Для исправления файлов, принятый ответ просто отлично.
— Ханс-Мартин Моснер

Ответы:


17

Control-L (обозначается как ^L) - это символ «подача формы». В ASCII он имеет десятичное значение 12 ( Lявляется 12-й буквой алфавита) или шестнадцатеричное значение 0c:

$ printf 'foo\x0cbar\n' | cat -et
foo^Lbar$

$ printf 'foo\x0cbar\n'
foo
   bar

Вы можете заменить его с помощью таких инструментов, как sed, указав шестнадцатеричный escape-код:

$ printf 'foo\x0cbar\n' | sed 's/\x0c//'
foobar

В качестве альтернативы, создавать ^Lнепосредственно с помощью клавиатуры последовательности CTRL+ V CTRL+L

sed 's/CTRL+VCTRL+L//'

Для вашей конкретной замены, учитывая

$ printf '<\x0cilename\n'
<
 ilename

тогда

$ printf '<\x0cilename\n' | sed 's/<\x0c/<\/f/g'
</filename

( gмодификатор добавляется, если в строке более одного экземпляра).


В моем случае "$ printf '<\ x0cilename \ n' | sed 's / <\ x0c / <\\ f / g'" не работает. Но, согласно вашему ответу, "$ find. -Exec perl -pi -e 's / <\ x0cilename> / <\ / filename> / g' {} \;" работает хорошо. Спасибо за ваш ответ :)
— Ян

@Yang извините, я только что понял, что перепутал косую черту и обратную косую черту в своем ответе (исправлено сейчас) - все еще не уверен, почему это помешало бы работать версии sed
— steeldriver

Очень хороший ответ! Было бы еще лучше, если бы он включал, например, a, findкоторый зацикливался на этих 50000 XML-файлах и автоматически обрабатывал каждый из них (и тоже делал резервную копию).
— Кингсли

2

Как отмечает Ханс-Мартин Моснер в комментариях, кажется, что кто-то использовал обратную косую черту вместо прямой косой черты при генерации XML (или, возможно, управлял всем <filename>разделом через конвертер Unix-в-Windows, который был слишком усердным в отношении косых черт ). \fявляется редко используемой escape-последовательностью для символа подачи формы, он же U + 0C или ^ L. Таким образом, на более позднем этапе конвейера заменили \fбуквенные символы U + 0C.

К счастью, U + 0C - чрезвычайно редкий символ, который вряд ли можно найти намеренно в любом виде XML. И так как только \fбудет производить это, в отличии от (например) \gили \k, универсальной находки и замены должны исправить не только , </filename>но и </folder>, </file>или что - нибудь еще , что получило искажаются.

Это то, что делает sed-скрипт Steeldriver; Я бы просто сделал это немного более общим:

sed 's|\x0c|/f|g'

Это означает, что «все действия \x0c(т. /fЕ. U + 0C) должны (g) лоббировать».


2

\fявляется символом подачи формы в Perl. Похоже, что эти искаженные файлы были созданы кем-то новым для Perl и XML.

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

\fможно просто использовать самому вместо шестнадцатеричного кода x0c.

find . -type f -exec perl -pi.bkp -e 's [ \f ilename ][ /f ilename ]gx' {} \;

Здесь я добавил -type fв tel findтолько возврат простых файлов - в противном случае findон вернется .в список и вызовет предупреждение при попытке его редактирования, хотя все остальное будет работать.

Я также сделал регулярное выражение более легким для просмотра, используя xфлаг, который игнорирует реальные пробелы, позволяя вам выделить элементы вашего регулярного выражения. Если вам не нравится это, вот это без:

find . -type f -exec perl -pi.bkp -e 's[\filename][/filename]g' {} \;

И в вероятном случае, когда все символы подачи формы являются ложными, и все они должны быть заменены /f, то вы можете еще больше уменьшить размер строки:

find . -type f -exec perl -pi.bkp -e 's[\f][/f]g' {} \;

Вам не нужно использовать косую черту, чтобы окружить элементы команды подстановки регулярных выражений ( s///) в Perl. Вы можете использовать любой символ. Однако, если вы решите использовать любой вид парного символа в скобках, вам придется использовать оба из них: s[old][new]например.

Поскольку я не использую косые черты, мне не нужно избегать косых черт.

Что касается -i.bkp: perl -pi -eпозволяет редактировать на месте - но если вам нужна дополнительная страховка на случай, если вы неправильно установили Perl-программу поиска, вы можете добавить расширение файла, чтобы оно сделало копию исходных файлов для вы. Здесь я использовал .bkp.

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

Вы должны рассмотреть возможность использования Perl для этих видов задач, потому что это чрезвычайно мощные , но недооцененным языком программирования общего назначения, один из которых оригинального дизайна цель был заменить sedи awkс чем - то гораздо лучше.

Возможности сопоставления регулярных выражений в Perl 5 и улучшенный синтаксис регулярных выражений намного превосходят возможности sed, awkи даже любой другой язык программирования, кроме Perl 6, что делает Perl наиболее разумным выбором как для простых, так и для расширенных манипуляций с регулярными выражениями.

Чтобы уточнить: sedс ним findтоже будет хорошо, и вы также можете использовать его sed -i.bkpдля создания резервной копии каждого отредактированного файла, но, насколько я знаю, он не имеет дополнительной устойчивости в Perl 5.28 и выше. Он также использует более грубый и гораздо менее мощный традиционный синтаксис регулярных выражений UNIX ®.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.