Мне нужно исключить файлы textClipping из списка. К сожалению, некоторые файлы были ужасно названы и содержат возврат каретки. Мне нужно регулярное выражение Perl для этого будет соответствовать каждый путь от /Volumes/ до .textClipping включая новую строку .

/Volumes/.*\.textClipping захватывает первые два файла .textClipping , но не третий, с новой строкой. В качестве альтернативы я смог захватить все, от первого /Volumes/ до последнего .textClipping , но это тоже не полезно.

Есть идеи? Огромное спасибо.

/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

3 ответа3

0

По вашему вопросу я не могу сказать, где в именах файлов могут быть символы новой строки, поэтому я предполагаю, что они могут быть где угодно. Это делает сопоставление более сложным.

Самое простое решение может состоять в том, чтобы удалить все символы новой строки из ввода перед удалением нежелательных имен файлов.

Я сделал этот скрипт:

#!/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";     

и скормил свой пример как 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

который дал этот вывод:

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

Наконец, я думаю, что вы должны быть очень осторожны, используя шаблон, который вы предлагаете в своем вопросе:

/Volumes/.*.textClipping

поскольку . захватит любой символ, кроме новой строки, но включая пробел. Я запустил этот шаблон на этом входе, как подсказывает ваш вопрос:

/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

и получил этот вывод, который я не думаю, что вы хотите:

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

Изменить: вы недавно опубликовали ответ на свой вопрос, где вы снова попали в эту ловушку, но у меня недостаточно репутации, чтобы оставить комментарий. Вместо /Volumes/.*\n*.textClipping/g (который будет соответствовать пробелам и, таким образом, потенциально избавится от более чем одного имени файла за раз), я настоятельно рекомендую рассмотреть /Volumes/[^ ]*\n*.textClipping/g ; [^ ]* будет соответствовать всему, кроме пробелов.

0

Вы могли бы сделать:

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

Куда:

  • -0777 прочитать файл в режиме "slurp"
  • -a режим автоматического разделения

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

Выход:

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

le.textClipping

Если вы хотите сохранить все файлы, которые не заканчиваются на .textClipping

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

Входной файл изменяется на месте (опция -i), исходный файл резервируется с расширением .orig

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

Я действительно ценю ответы. Спасибо за ваше время. Я прошу прощения, если что-то не было ясно в моем вопросе. Ответ оказался проще, чем я думал вначале.

Отметим, что возврат каретки или новая строка в имени файла выглядит следующим образом: «file (CR)name.textClipping». Текстовые файлы просто дают текст, содержащийся в качестве имени самого файла, что в моем случае - несколько возвратов каретки. Боль в заднице!

Тем не менее, это работает:/Volumes/.*\n*.textClipping/g

Это совпадает со строками вхождений, начинающимися с "/Volumes/" и заканчивающимися на ".textClipping" со всем, что между ними.

Еще раз спасибо за ваши предложения.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .