Вопрос по string, perl – Как я могу развернуть строку вроде «1..15,16» в список чисел?

5

У меня есть приложение 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-последовательности, но не повезло.

Можно ли это сделать таким образом?

Ваш Ответ

6   ответов
1

@arr2 = eval($str); Поскольку вы принимаете участие и оцениваете его, вы должны быть осторожны. Вы должны вероятно@arr2 = eval($str) if ($str =~ m/^[0-9.,]+$/)

Постскриптум Я не знал о пакете Number :: Range, но онклассно, Number :: Range ftw.

26

не используйте строку eval, если у вас есть какие-либо проблемы с безопасностью.

Попробуйте использоватьКоличество :: Диапазон вместо:

 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

Там такжеНабор :: IntSpan, который использует - вместо ..:

 use Set::IntSpan;

 $str = "1-15,16";
 @arr2 = Set::IntSpan->new( $str )->elements;

но он требует, чтобы диапазоны были в порядке и не перекрывались (он был написан для использования в файлах .newsrc, если кто-нибудь помнит, что это такое). Это также позволяет бесконечные диапазоны (где начинается строка -number или заканчиваетсяnumber-), который будет прокачивать метод элементов.

Я никогда раньше не сталкивался с Number :: Range. Я сохранил это для дальнейшего использования. Спасибо, что сообщили мне об этом!
Вот почему вы всегда проверяете работоспособность пользовательского ввода перед его использованием.
@Mathieu Longtin: вопрос подразумевает, что это индексы некоторых других, уже находящихся в памяти, данных. поэтому не будет никакого такого диапазона.
Если вы примете пользовательский ввод, ваше приложение взорвется на 1..1000000000, если у вас нет около 8 ГБ оперативной памяти. Number :: Range-> gt; size () сейчас бесполезен, чтобы предотвратить это, поскольку он генерирует весь диапазон для определения размера.
+1. & quot; Делать все правильно & quot; всегда предпочтительнее, чем eval. Гораздо меньше побочных эффектов.
-2

Use split:<,/p>

@parts = split(/\,/, $fields);

print $parts[0];
1-6
print $parts[1];
8

Вы не можете просто поместить строку, содержащую ",", " в массиве и ожидаем, что он превратится в элементы (кроме случаев, когда вы используете какую-то черную магию Perl, но мы не будем вдаваться в подробности здесь)

Но Regex и split - ваши друзья.

Error: User Rate Limit Exceeded sud03r
-1

Вы можете использовать eval:

$str = "1..15,16" ;
@arr2 = ( eval $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;

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

1

: Vector :: to_Enum. Я решил это, выполнив:

$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;

тогда также в моем файле:

sub expand_range
{
    return join(",",($_[0] .. $_[1]));
}

Итак, «1,3,5-7,9,12-15» превращается в "1,3,5,6,7,9,12,13,14,15".

Я очень старался поместить это расширение во 2-ю часть s ///, поэтому мне не понадобится эта дополнительная функция, но я не смог заставить ее работать. Мне это нравится, потому что хотя Number :: Range будет работать, таким образом, мне не придется загружать другой модуль для чего-то, что должно быть тривиальным.

0
@arr2 = ( eval $str ) ;

Работает, хотя, конечно, вы должны быть очень осторожны с eval ().

Error: User Rate Limit Exceeded sud03r

Похожие вопросы