Saya perlu mengekstrak string teks dari satu file yang berisi satu baris teks yang sangat panjang tanpa pembatas. Menggunakan contoh baris di bawah ini, ini adalah fakta yang diketahui berikut:
??????? A1XXXXXXXXXX ??????? B1XXXX ??????? A1XXXXXXXXXX ??????? C1XXXXXXX
1. It contains 38 fixed width record types
2. The record marker is a 7 alphanumeric character followed by, for example, ‘A1’.
3. Each record type has varying widths, for example, A1 record type will have 10 characters following it, if B1 then 4, and if C1 then 7.
4. The record types aren’t clumped together and can be in any order. As in the example, its A1,B1,A1,C1
5. The example above has 4 records and each record type needs to go to separate files. In this case 38 of them.
??????? A1XXXXXXXXXX
??????? B1XXXX
??????? A1XXXXXXXXXX
??????? C1XXXXXXX
6. The record identifier, e.g. ????????A1, can appear in the body of the record so cannot use grep.
7. With the last point in mind, I was proposing 3 solutions but not sure on how to script this and of course would greatly appreciate some help.
a. Traverse through the file from the beginning and sequentially strip out the record to the appropriate output file. For example, strip out first record type A1 to A1file which I know is 10 characters long then re-interrogate the file which will then have B1 which I know is 4 chars long, strip this out to B1file etc.. <<< this seems painful >>
b. Traverse through the file and append some obscure character to each record marker within the same file. Much like above but not strip out. I understand it still will use the same logic but seems more elegant
c. I did think of simply using the proposed grep -oE solution but then re-interrogate the output files to see if any of the 38 record markers exist anywhere other than at the beginning. But this might not always work.
text-processing
sed
awk
jags
sumber
sumber
Jawaban:
Bagaimana tentang grep
Ini mencetak setiap catatan dari setiap jenis catatan pada baris yang terpisah. Untuk mengarahkan
grep
output ke 3 file bernamaA1
,B1
,C1
masing-masing,sumber
Berikut adalah solusi yang memungkinkan menggunakan FPAT gawk
Sebagai one-liner:
sumber
FPAT
membutuhkan versi gawk 4. Lihat: linuxjournaldigital.com/linuxjournal/201109#pg98Dalam Perl:
Ajukan sebagai:
Kode diuji dan berfungsi dengan input yang Anda berikan.
Memperbarui
Dalam komentar Anda, Anda meminta "Unix equivalent" di atas. Saya sangat meragukan ada hal seperti itu, karena ekspresi Perl yang digunakan untuk menguraikan baris Anda adalah ekspresi yang sangat tidak teratur dan saya ragu bahwa ekspresi reguler vanila dapat mem-parsing format data yang Anda berikan: itu terlalu mirip dengan jenis ekspresi yang terkenal yang dapat regex dapat parse (cocok dengan angka berapa pun
a
diikuti dengan angka yang samab
).Bagaimanapun, pendekatan "Unix" terdekat yang dapat saya temukan adalah generalisasi jawaban 1_CR . Anda harus mencatat bahwa pendekatan ini khusus untuk implementasi GNU
grep
dan karenanya tidak akan berfungsi pada sebagian besar Unix. Pendekatan Perl, sebaliknya, harus bekerja sama pada platform apa pun yang bekerja pada Perl. Inilahgrep
pendekatan GNU yang saya sarankan :Memperbarui
Berdasarkan permintaan OP di komentar, alih-alih meneruskan nama file sebagai argumen baris perintah, itu dapat dibuka di dalam skrip seperti:
Ini mengasumsikan Anda telah mendeklarasikan variabel
$input_file_name
berisi, yah, nama file input.Sedangkan untuk menambahkan stempel waktu ke nama file output, Anda dapat menggunakan
qx{}
sintaks: antara kawat gigi Anda dapat menempatkan perintah Unix apa pun yang Anda inginkan dan itu akan dijalankan dan output standarnya dibaca kembali di tempatqx{}
operator:The
qx
operator tidak terbatas pada kawat gigi, menggunakan karakter favorit Anda sebagai pembatas, hanya pastikan itu bukan dalam perintah yang Anda butuhkan untuk menjalankan:dan seterusnya...
Dalam beberapa kode Perl Anda mungkin melihat backticks (
` `
) digunakan untuk melayani fungsi ini sebagai gantinya, mirip dengan apa yang dilakukan shell. Anggap sajaqx
operator sebagai generalisasi dari backticks ke pembatas mana pun.Ngomong-ngomong, ini akan memberikan stempel waktu yang sedikit berbeda untuk setiap file (jika perbedaan waktu pembuatannya adalah jumlah detik yang terbatas). Jika Anda tidak menginginkan ini, Anda dapat melakukannya dengan dua langkah:
sumber