Regex dari substring ke kemunculan pertama substring lain

0

Saya perlu menghilangkan file textClipping dari daftar. Sayangnya beberapa file telah sangat dinamai dan mengandung carriage return. Saya membutuhkan perl regex untuk itu akan cocok dengan setiap jalur dari /Volumes/ untuk .textClipping termasuk baris baru.

/Volumes/.*\.textClipping menangkap dua yang pertama .textClipping file, tetapi bukan yang ketiga, dengan baris baru. Atau saya bisa menangkap semuanya dari dulu /Volumes/ untuk bertahan .textClipping, tapi itu juga tidak membantu.

Ada ide? Terima kasih banyak.

/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/fi  

le.textClipping
/Volumes/folder/folder/file.doc
Robert Koszegi
sumber

Jawaban:

0

Anda bisa melakukannya:

perl  -0777 -ae '@files = m~(/Volumes/(?:[^/\r\n]+/)+?[^/]+?\.textClipping\R)~g;print scalar(@files)," files found:\n",@files' file.txt

Dimana:

  • -0777 baca file dalam mode "slurp"
  • -a mode autosplit

Regex:

 ~                      : regex delimiter
(                       : start group 1
    /Volumes/           : literally 
    (?:                 : start non capture group
        [^/\r\n]+       : 1 or more any character that is not a slash or line break
        /               : slash
    )+?                 : group repeated 1 or more times, not greedy (ie. the path)
    [^/]+?              : not a slash, 1 or more times, not greedy (ie. the filename)
    \.textClipping      : a dot with the extension
    \R                  : any kind of linebreak
)                       : end group 1
~g                      : regex delimiter, global flag

Keluaran:

3 files found:
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/fi

le.textClipping

Jika Anda ingin menyimpan semua file yang tidak berakhir dengan .textClipping

perl  -0777 -i.orig -ape 's~(/Volumes/(?:[^/\r\n]+/)+?[^/]+?\.textClipping\R)~~g' file.txt

File input dimodifikasi di tempat (opsi -i ), file asli dicadangkan dengan ekstensi .orig

cat file.txt
/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.doc
Toto
sumber
0

Saya sangat menghargai tanggapannya. Terima kasih atas waktu Anda. Saya minta maaf jika ada yang tidak jelas dalam pertanyaan saya. Jawabannya ternyata lebih sederhana dari yang saya pikirkan.

Untuk diketahui, carriage return atau baris baru dalam nama file adalah sebagai berikut: "file (CR) name.textClipping". File textclipping hanya memberikan teks yang terkandung dalam nama file itu sendiri, yang dalam kasus saya adalah beberapa carriage return. Nyeri di pantat!

Namun demikian, ini berfungsi: /Volumes/.*\n*.textClipping/g

Ini cocok dengan string kejadian yang dimulai dengan "/ Volume /", diakhiri dengan ".textClipping" dengan segala sesuatu di antaranya.

Sekali lagi terima kasih atas saran Anda.

Robert Koszegi
sumber
Apakah Anda yakin ini berfungsi seperti yang Anda inginkan? Terapkan pada file sampel yang diberikan, itu memberikan untuk pertandingan 2 file yang cocok (baris 3 digabungkan dengan baris 4)
Toto
0

Saya tidak tahu dari pertanyaan Anda di mana dalam nama file karakter baris baru bisa, jadi saya berasumsi mereka bisa berada di mana saja. Ini membuat pencocokan lebih menantang.

Solusi paling sederhana mungkin dengan menghapus semua baris baru dari input sebelum menghapus nama file yang tidak diinginkan.

Saya membuat skrip ini:

#!/usr/bin/perl                                                                                                                                            
$filename = "filelist.txt";                                                                                                                                
open(FILE, $filename) or die "Cant open $filename\n";                                                                                                      

# Undefine the record separator, so that the entire file will be read into a single string
# instead of an array with records separated by newlines
local $/ = undef;                                                                                                                                          
$lines = <FILE>;                                                                                                                                           
close(FILE);                                                                                                                                               
print "Before\n------\n";                                                                                                                                  
print $lines;                                                                                                                                              

# Remove all newlines                                                       
$lines =~ s/\n+//g;                                                                                                                                        
# Remove all "textClipping" files
$lines =~ s/\/Volumes\/[^ ]*.textClipping//g;                                                                                                              
# Turn multiple consecutive spaces into single spaces
$lines =~ s/ +/ /g;                                                                                                                                        

print "After\n-----\n";                                                                                                                                    
print "$lines\n";     

dan berikan contoh Anda sebagai filelist.txt:

/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc

yang memberikan hasil ini:

Before
------
/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc
After
-----
/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.doc

Akhirnya, saya pikir Anda harus sangat berhati-hati menggunakan pola yang Anda sarankan dalam pertanyaan Anda:

/Volumes/.*.textClipping

sejak . akan menangkap karakter apa pun kecuali baris baru, tetapi termasuk spasi. Saya menjalankan pola itu pada input ini seperti yang disarankan oleh pertanyaan Anda:

/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc

dan dapatkan hasil ini, yang menurut saya bukan yang Anda inginkan:

/Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc

Edit : Anda baru saja memposting Jawaban untuk pertanyaan Anda sendiri di mana Anda jatuh ke dalam perangkap ini lagi, tetapi saya tidak memiliki Reputasi yang cukup untuk memposting komentar di atasnya. Dari pada /Volumes/.*\n*.textClipping/g (yang akan cocok dengan spasi, dan dengan demikian berpotensi menghilangkan lebih dari satu nama file sekaligus) Saya sangat menyarankan Anda mempertimbangkannya /Volumes/[^ ]*\n*.textClipping/g; itu [^ ]* akan cocok dengan semuanya kecuali spasi.

FosseWay
sumber