Bagaimana saya bisa mengubah kode ^ L di banyak file di Ubuntu?

8

Saya memiliki banyak file XML, lebih dari 50.000.

Dalam beberapa file XML, beberapa file ditulis seperti ini

<filename>abc.JPEG<^Lilename>

^Lhanya satu karakter, tetapi saya tidak dapat menemukan apa ^Lartinya dengan Google.

Ketika saya gunakan catuntuk mencetak konten file, itu menunjukkan seperti berikut

<filename>abc.JPEG<
                   ilename>

Lagi pula, saya ingin berubah <filename>abc.JPEG<^Lilename>menjadi<filename>abc.JPEG</filename>

Saya sudah menemukan beberapa perintah untuk mengubah kata di banyak file, seperti

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

Tetapi perintah itu tidak berfungsi dalam kasus saya, karena tidak dapat mengenali kata pencarian ketika saya mengetik ^L.

Bagaimana cara mengubah <filename>abc.JPEG<^Lilename>ke <filename>abc.JPEG</filename>dalam banyak file?

Yang
sumber
6
Rupanya seseorang digunakan <\filename>alih-alih </filename>dalam konteks di mana \fakan diartikan sebagai bentuk feed karakter. Anda mungkin harus melacak sumber file-file ini dan menunjukkan masalah dengan alat pembangkitnya kepada pengembang. Untuk memperbaiki file, jawaban yang diterima baik-baik saja.
Hans-Martin Mosner

Jawaban:

17

Control-L (diwakili sebagai ^L) adalah karakter "form feed". Dalam ASCII, ia memiliki nilai desimal 12 ( Ladalah huruf ke-12 dari alfabet) atau nilai hex 0c:

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

$ printf 'foo\x0cbar\n'
foo
   bar

Anda dapat menggantinya menggunakan alat seperti sed dengan menentukan kode escape heksadesimal:

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

Atau, buat komposisi ^Llangsung menggunakan urutan keyboard CTRL+ V CTRL+L

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

Untuk penggantian spesifik Anda, diberikan

$ printf '<\x0cilename\n'
<
 ilename

kemudian

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

( gpengubah ditambahkan jika ada lebih dari satu contoh per baris).

Steeldriver
sumber
Dalam kasus saya, "$ printf '<\ x0cilename \ n' | sed 's / <\ x0c / <\\ f / g'" tidak berfungsi. Tetapi, menurut jawaban Anda, "$ find. -Exec perl -pi -e 's / <\ x0cilename> / <\ / filename> / g' {} \;" bekerja dengan baik. Terima kasih atas jawaban Anda :)
Yang
@Yang maaf saya baru sadar bahwa saya bingung mem-forward slash dan backslash dalam jawaban saya (dikoreksi sekarang) - masih tidak yakin mengapa hal itu akan mencegah versi sed bekerja
steeldriver
Jawaban yang sangat bagus! Akan lebih baik jika itu termasuk mengatakan findyang di-loop atas 50000 file-file XML dan secara otomatis diproses masing-masing (dan membuat cadangan juga).
Kingsley
2

Seperti yang ditunjukkan oleh Hans-Martin Mosner dalam komentar, tampaknya seseorang menggunakan garis miring terbalik alih-alih garis miring ketika membuat XML (atau mungkin menjalankan seluruh <filename>bagian melalui konverter Unix-to-Windows yang terlalu bersemangat tentang garis miring). \fadalah urutan pelarian yang jarang digunakan untuk karakter umpan bentuk, alias U + 0C atau ^ L. Jadi beberapa langkah selanjutnya dari pipeline kemudian diganti \fdengan karakter literal U + 0C.

Untungnya, U + 0C adalah karakter yang sangat langka yang tidak mungkin ditemukan dengan sengaja dalam bentuk XML apa pun. Dan karena hanya \fakan menghasilkan ini, sebagai lawan (katakanlah) \gatau \k, menemukan-dan-ganti universal yang harus memperbaiki tidak hanya </filename>tetapi juga </folder>, </file>, atau apa pun yang mendapat hancur.

Itu yang dilakukan oleh sed-script steeldriver; Saya hanya akan membuatnya sedikit lebih umum:

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

Ini berarti "(s) wap semua instance \x0c(yaitu, U + 0C) ke /f, (g) secara lobal".

Draconis
sumber
2

\fadalah karakter umpan formulir di Perl. Sepertinya file-file cacat ini dibuat oleh seseorang yang baru untuk Perl dan XML.

Berikut adalah banyak perbaikan Perlier - yang juga memenuhi tujuan OP mengotomatiskan pembaruan semua file, tidak seperti jawaban yang diterima dengan sed, yang hanya akan bekerja pada satu file pada satu waktu karena tidak dipasangkan find.

\fhanya bisa digunakan sendiri bukan kode heksadesimal x0c.

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

Di sini saya telah menambahkan -type fke tel finduntuk hanya mengembalikan file biasa - jika tidak findakan kembali .dalam daftar, dan memicu peringatan ketika Anda mencoba mengeditnya, meskipun semuanya masih berfungsi.

Saya juga membuat regex lebih mudah dilihat dengan menggunakan xflag yang mengabaikan spasi putih nyata, memungkinkan Anda untuk menghilangkan elemen-elemen dari regex Anda. Jika Anda tidak suka ini, ini dia tanpa:

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

Dan dalam hal kemungkinan bahwa semua karakter umpan formulir adalah palsu dan semua harus diganti /f, maka Anda dapat melangsingkan satu baris lebih jauh:

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

Anda tidak perlu menggunakan garis miring maju untuk mengelilingi elemen perintah substitusi regex Anda ( s///) di Perl. Anda bisa menggunakan simbol apa saja. Namun, jika Anda memilih untuk menggunakan jenis simbol seperti braket apa pun, Anda harus menggunakan keduanya: s[old][new]misalnya.

Karena saya tidak menggunakan garis miring, saya tidak perlu melepaskan garis miring.

Adapun -i.bkp: perl -pi -ememungkinkan Anda mengedit di tempat - tetapi jika Anda ingin asuransi tambahan jika Anda salah menemukan dan mengganti program Perl, Anda dapat memasukkan ekstensi file sehingga akan membuat salinan file asli untuk kamu. Di sini, saya sudah menggunakan .bkp.

Dalam versi terbaru dari Perl, pengeditan di tempat telah diperbarui agar lebih tangguh jika sistem Anda mengalami masalah serius seperti kehilangan daya atau kehabisan ruang disk juga. Inilah Perl penulis brian d foy pada peningkatan pengeditan di tempat di Perls baru-baru ini.

Anda harus mempertimbangkan untuk menggunakan Perl untuk tugas-tugas semacam ini, karena ini adalah bahasa pemrograman tujuan umum yang sangat kuat namun di bawah rata-rata, salah satu yang tujuan desain awalnya adalah untuk menggantikan seddan awkdengan sesuatu yang jauh lebih baik.

Kemampuan pencocokan regex Perl 5 dan ditingkatkan sintaks regex jauh melebihi orang-orang dari sed, awk, dan memang setiap bahasa pemrograman lain selain Perl 6, membuat Perl pilihan yang paling masuk akal untuk kedua sederhana dan manipulasi regex maju.

Untuk memperjelas: sedakan bekerja dengan baik findjuga dan Anda juga dapat menggunakan sed -i.bkpuntuk membuat cadangan dari setiap file yang diedit, tetapi sejauh yang saya tahu itu tidak menampilkan ketahanan ekstra di Perl 5.28 dan di atasnya. Itu juga menggunakan sintaks regex UNIX ® clunkier dan jauh lebih kuat.

Medlock Perlman
sumber