Як я можу змінити ^ 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це дванадцята літера алфавіту) або шістнадцяткове значення 0c:

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

$ printf 'foo\x0cbar\n'
foo
   bar

Ви можете замінити його за допомогою інструментів типу sed, вказавши шістнадцятковий код втечі:

$ 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> / <\ / ім'я файлу> / g' {} \;" працює добре. Дякуємо за вашу відповідь :)
Ян

@ Yang вибачте, що я просто зрозумів, що я переплутав нахил вперед і нахил у своїй відповіді (виправлено зараз) - все ще не впевнений, чому це завадило б працювати версії sed, хоча
steeldriver

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

2

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

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

Ось що робить sed-скрипт steeldriver; Я б просто зробив це трохи більш загальним:

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

Це означає, що "(s) перекачувати всі екземпляри \x0c(тобто U + 0C) до /f, (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 Браян d foy щодо вдосконаленого редагування на місці в останніх 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.