Perl Регулярное выражение удаляет двойные табуляции, разрывы строк, пробелы - PullRequest
1 голос
/ 28 декабря 2010

Я хочу написать Perl-скрипт, который удаляет двойные табуляции, разрывы строк и пробелы.

Пока у меня есть:

$txt=~s/\r//gs;
$txt=~s/ +/ /gs;
$txt=~s/\t+/\t/gs;
$txt=~s/[\t\n]*\n/\n/gs;
$txt=~s/\n+/\n/gs;

Но 1. Это не красиво,Должно быть возможно сделать это с гораздо меньшим количеством регулярных выражений.2. Это просто не работает, и я действительно не знаю, почему.Он оставляет несколько двойных табуляций, пробелов и пустых строк (то есть строк только с табуляцией или пробелами)

Я мог бы решить это некоторое время, но это очень медленно и безобразно.предложения?

Ответы [ 4 ]

3 голосов
/ 28 декабря 2010

У вас там что-то вроде мешанины, не все из которых соответствуют тому, что вы сказали. Давайте разберем, что у вас есть, и тогда, возможно, вы сможете работать оттуда к тому, что вы хотите.

$txt=~s/\r//s; # removes a single \r from the line. Did you mean to use g on this one?
$txt=~s/[\t ]\n//s; # match a single \t OR space right before a \n, and remove. 
$txt=~s/ +/ /gs;# match at least 2 spaces, replace with a single space
$txt=~s/\t+/ /gs;# match at least 2 \t, replace with a single space
$txt=~s/\n /\n/s;# remove a space immediately following a \n
$txt=~s/\t /\t/s;# remove a space immediately following a \t
$txt=~s/\n+/ /gs;# match at least 2 \n, replace them all with a single space

У меня такое ощущение, что это совсем не то, чего вы хотите достичь.

Мне, честно говоря, неясно, что вы хотите сделать. При прочтении вашего заявленного намерения я бы подумал, что вы захотите заменить все двойные табуляции на отдельные табуляции, все двойные разрывы строк на одиночные разрывы строк, а все двойные пробелы на одинарные пробелы. Кроме того, я предполагаю, что вы на самом деле хотите сыграть этих персонажей, а не просто удваивать. Вот регулярные выражения для того, что я только что сказал, надеюсь, это даст вам кое-что для продолжения: (Я также удалил все \ r).

$txt=~s/\r//gs;# remove all \r
$txt=~s/\t+/\t/gs;# replace all runs of > 1 tab with a single tab
$txt=~s/\n+/\n/gs;# replace all runs of > 1 \n with a single \n
$txt=~s/ +/ /gs;# replace all runs of > 1 space with a single space

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

2 голосов
/ 28 декабря 2010

Я не уверен в ваших точных требованиях, но вот несколько советов, которые могут вас заставить:

Сжать все пробелы в пробелы (возможно, слишком мощные!)

$txt=~s/\s+/ /g ;

Чтобы удалить пробелы в начале строки

$txt=~s/^ +//gm ;

Чтобы сжать несколько вкладок до пробела

$txt=~s/\t+/ /g ;
2 голосов
/ 28 декабря 2010

Когда я пытаюсь найти быстрый реальный ответ для вас, вы смотрели документы (нет, я не просто говорю rtfm). perldoc - отличный инструмент, и в нем есть полезная информация. Могу я предложить perldoc perlrequick и perldoc perlreref, чтобы вы начали.

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

Наконец, мне кажется, что при работе с длинным блоком текста этот текст, вероятно, будет внешним по отношению к вашему сценарию. Если вы действительно открываете файл и помещаете его в переменную, вам будет проще сделать то, что я оставляю как блок комментариев. Чтобы использовать этот метод, закомментируйте первый блок и удалите комментарий о втором блоке, третий блок остается для любого метода. Я включил это, потому что, если вы действительно читаете файл, а затем разбиваете его, это экономит много работы, просто читая его построчно. Затем вы можете записать его в другой файл, если хотите.

#!/usr/bin/env perl

use strict;
use warnings;

my @return_lines;

### Begin "text in script" Method ###
my $txt = <<END;
hello  world  

 hello world  
hello    world
hello   world
END
#note last two are to test removing spaces after tabs

my @lines = split(/\n/, $txt);
foreach my $line (@lines) {

### Begin "text in external file" Method (commented) ###
#my $filename = 'file.txt';
#open( my $filehandle, '<', $filename); 
#while (<$filehandle>) {
#  my $line = $_; 

### Script continues for either input method ###
  $line =~ s/^\s*//; #remove leading whitespace
  $line =~ s/\s*$//; #remove trailing whitespace
  $line =~ s/\ {2,}/ /g; #remove multiple literal spaces
  $line =~ s/\t{2,}/\t/g; #remove excess tabs (is this what you meant?)
  $line =~ s/(?<=\t)\ *//g; #remove any spaces after a tab 
  push @return_lines, $line unless $line=~/^\s*$/; #remove empty lines
}
my $return_txt = join("\n", @return_lines) . "\n";

print $return_txt;
1 голос
/ 28 декабря 2010

Это немного неясно.

Если у вас есть строка типа ab TABcTABTAB \n\n, что вы хотите в результате? Я читаю выше, как ab c\n? - ДВК 1 минуту назад редактировать

Другими словами, правильно ли вы хотите:

  1. Все пробелы (например, любое количество пробелов и табуляций) в середине строк преобразованы в один пробел?

  2. Все пробелы в начале ИЛИ в конце строки удалены (кроме новых строк)?

  3. Удалить полностью пустые строки?

    $s =~ s/[\t ]+$//ms; # Remove ending spaces/tabs
    $s =~ s/^[\t ]+//ms; # Remove starting spaces/tabs
    $s =~ s/[\t ]+/ /ms; # Replace duplicate whitespace mid-string with 1 space
    $s =~ s/^$//ms;      # Remove completely empty lines
    

Обратите внимание, что я использовал модификаторы "/ ms" (подробнее см. perdoc perlre ), чтобы я мог использовать начало / конец якоря строки в многострочной строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...