У программиста в файле хранилась таблица:
> cat table.txt
|Alan|blue|168|23
|Brendon|green|178|36
|Carlyle|brown|190|50
|David|brown|180|20
Программисту понадобилось удалить последнюю колонку в этой таблице, и он попробовал сделать это с помощью Perl-однострочника:
> perl -lne '@a = split "|"; pop @a; print join "|", @a;' table.txt > result.txt
Но…
В новом файле оказалась полная чушь:
> cat result.txt
||A|l|a|n|||b|l|u|e|||1|6|8|||2
||B|r|e|n|d|o|n|||g|r|e|e|n|||1|7|8|||3
||C|a|r|l|y|l|e|||b|r|o|w|n|||1|9|0|||5
||D|a|v|i|d|||b|r|o|w|n|||1|8|0|||2
Функция split в качестве первого параметра принимает не просто строку, но регулярное выражение.
Проблема в символе “ | ”, по которому программист пытается разбить строку на поля. |
Так как первый параметр split’а – регулярное выражение, split '|', $str
работает так же, как split m/|/, $str
, или split m//, $str
, или split '', $str
Ну а split по пустому регулярному выражению разбивает строку на отдельные символы. Так что
split "|", "|Alan|blue"
дает список ("|", "A", "l", "a", "n", "|", "b", "l", "u", "e")
, и потом эти списки символов просто были склеены через “|”.
Хорошим вариантом было бы квотировать спецсимволы:
> perl -lne '@a = split /\|/; pop @a; print join "|", @a;' table.txt
|Alan|blue|168
|Brendon|green|178
|Carlyle|brown|190
|David|brown|180
Или можно воспользоваться автоматическим разбиением входных строк, которое включается параметром -a
(разделитель для split’а указывается ключом -F
):
> perl -F'\|' -alne 'pop @F; print join "|", @F;' table.txt
|Alan|blue|168
|Brendon|green|178
|Carlyle|brown|190
|David|brown|180