Как заменить несколько пробелов одним пространством на Perl?

Почему это не работает?

$data = "What    is the STATUS of your mind right now?";

$data =~ tr/ +/ /;

print $data;

Ответ 1

Используйте $data =~ s/ +/ /; вместо этого.

Пояснение:

tr - оператор translation. Важно отметить, что модификаторы регулярных выражений не применяются в операторе перевода (кроме -, который все еще указывает диапазон). Поэтому, когда вы используете tr/ +/ / вы говорите: "Возьмите каждый экземпляр пространства символов и + и переведите их в пространство". Другими словами, tr думает о пространстве и + как отдельные символы, не регулярное выражение.

Демонстрация:

$data = "What    is the STA++TUS of your mind right now?";

$data =~ tr/ +/ /;

print $data; #Prints "What    is the STA  TUS of your mind right now?"

Использование s делает то, что вы ищете, говоря: "сопоставляйте любое количество последовательных пробелов (хотя бы один экземпляр) и заменяйте их одним пробелом". Вы также можете использовать что-то вроде
s/ +/ /g;, если имеется более одного места, в котором вы хотите, чтобы была выполнена замена (g означает, что нужно применять глобально).

Ответ 2

Вы также можете использовать tr с параметром "сквош", который удалит дублированные замененные символы. Подробнее см. perlop.

my $s = "foo      bar   fubb";
$s =~ tr/ //s;

Ответ 3

Perl 5.10 имеет новый класс символов, \h, обозначает горизонтальные пробелы, которые хороши для такого рода вещей:

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