Как я могу расширить строку типа “1 ..15,16” в список чисел?
Вопрос
У меня есть приложение Perl, которое принимает из командной строки входные данные в виде:
application --fields 1-6,8
Мне необходимо отобразить поля в соответствии с запросом пользователя в командной строке.
Я подумал о замене '-' на '..', чтобы я мог сохранить их в массиве, например
$str = "1..15,16" ;
@arr2 = ( $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;
Проблема здесь в том, что @arr работает нормально (как и должно быть ), но в @arr2 вся строка не расширяется как элементы массива.
Я пробовал использовать escape-последовательности, но безуспешно.
Можно ли это сделать таким образом?
Решение
Если это ввод пользователя, не используйте строку eval, если у вас есть какие-либо проблемы с безопасностью.
Попробуйте вместо этого использовать Number :: Range :
use Number::Range;
$str = "1..15,16" ;
@arr2 = Number::Range->new( $str )->range;
print for @arr2;
Чтобы избежать смерти в недопустимом диапазоне, выполните:
eval { @arr2 = Number::Range->new( $str )->range; 1 } or your_error_handling
Существует также Set :: IntSpan , который использует - вместо ..: р>
use Set::IntSpan;
$str = "1-15,16";
@arr2 = Set::IntSpan->new( $str )->elements;
но он требует, чтобы диапазоны были в порядке и не перекрывались (он был написан для использования в файлах .newsrc, если кто-нибудь помнит, что это такое). Он также допускает бесконечные диапазоны (где строка начинается - число или заканчивается число -), на которые будет распространяться метод элементов.
Другие советы
Ты думаешь о @arr2 = eval($str);
Поскольку вы принимаете входные данные и оцениваете их, вам нужно быть осторожным.Вероятно , вам следует @arr2 = eval($str) if ($str =~ m/^[0-9.,]+$/)
P.S.Я не знал о пакете Number:: Range, но это потрясающе.Номер::Дальность ftw.
У меня была та же проблема, связанная с выводом Bit :: Vector :: to_Enum. Я решил это, выполнив:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
затем также в моем файле:
sub expand_range
{
return join(",",( У меня была та же проблема, связанная с выводом Bit :: Vector :: to_Enum. Я решил это, выполнив:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
затем также в моем файле:
<*>
Итак "1,3,5-7,9,12-15" превращается в "1,3,5,6,7,9,12,13,14,15".
Я очень старался поместить это расширение во 2-ю часть s ///, чтобы мне не понадобилась эта дополнительная функция, но я не мог заставить ее работать. Мне это нравится, потому что хотя Number :: Range будет работать, таким образом, мне не нужно тянуть в другой модуль что-то тривиальное.
[0] .. У меня была та же проблема, связанная с выводом Bit :: Vector :: to_Enum. Я решил это, выполнив:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
затем также в моем файле:
<*>
Итак "1,3,5-7,9,12-15" превращается в "1,3,5,6,7,9,12,13,14,15".
Я очень старался поместить это расширение во 2-ю часть s ///, чтобы мне не понадобилась эта дополнительная функция, но я не мог заставить ее работать. Мне это нравится, потому что хотя Number :: Range будет работать, таким образом, мне не нужно тянуть в другой модуль что-то тривиальное.
[1]));
}
Итак "1,3,5-7,9,12-15" превращается в "1,3,5,6,7,9,12,13,14,15".
Я очень старался поместить это расширение во 2-ю часть s ///, чтобы мне не понадобилась эта дополнительная функция, но я не мог заставить ее работать. Мне это нравится, потому что хотя Number :: Range будет работать, таким образом, мне не нужно тянуть в другой модуль что-то тривиальное.
@arr2 = ( eval $str ) ;
Работает, хотя, конечно, вы должны быть очень осторожны с eval ().
Вы можете использовать eval:
$str = "1..15,16" ;
@arr2 = ( eval $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;
Хотя, если это пользовательский ввод, вам, вероятно, нужно сначала выполнить некоторую проверку входной строки, чтобы убедиться, что они не вводят ничего хитрого.
Использовать разделение:
@parts = split(/\,/, $fields);
print $parts[0];
1-6
print $parts[1];
8
Вы не можете просто поместить строку, содержащую ',' в массив, и ожидать, что она превратится в элементы (кроме случаев, когда вы используете некоторую черную магию Perl, но мы не будем вдаваться в подробности)
Но Regex и split - ваши друзья.