2010-09-11 2 views
4

Если есть, я, конечно, не вижу его. Мы снимаем магнитную полосу с водительских прав. Данные не кажутся последовательными. Стандарт, которым должны следовать лицензии водителя, устанавливает ограничения на длину, которую может иметь любое одно поле. Часть, с которой я не могу обернуть голову, состоит в том, как анализировать эти данные.Есть ли способ разобрать эти строки?

Например, поле может содержать 13 общих символов, но только 8. В этом случае всегда будет ограничитель каретки, заканчивающий эту часть строки. Тем не менее, и здесь сложная часть, если поле ровно 13 (из 13 допустимых), нет разделителя конца каретки и нет правильного заполнения. Все данные просто работают вместе.

Ниже приведены две строки примеров.

%CAMISSION HILLSSMITH$JOHN$JIM$JR^1147 SOMESTREET^? 
%CALOS ANGELES^DOE$JOHN$CARL^14324 MAIN ST APT 5^? 

Использование PHP, как я могу это сделать? Я бы по достоинству оценил это. Я действительно в тупике.

ответ

5

Хорошо, здесь мы идем. Я использовал флаг x, чтобы сделать регулярное выражение более удобочитаемым и прокомментировать его.

Из спецификации @EboMike, каждое поле имеет максимальную длину и заканчивается на ^, если оно короче этой длины. Имя представляет собой составное поле, используя $ как разделитель между фамилией, именем, именем и суффиксом. То же самое касается адреса, который использует $, если адрес имеет несколько строк.

$licenses = array(
    '%CAMISSION HILLSSMITH$JOHN$JIM$JR^1147 SOMESTREET^?', 
    '%CALOS ANGELES^DOE$JOHN$CARL^14324 MAIN ST APT 5^?' 
); 

foreach ($licenses as $license) { 
    preg_match(
     '@ 
      ^% 
      (.{2})   # State, 2 chars 
      ([^^]{0,12}.) # City, 13 chars, delimited by^
      ([^^]{0,34}.) # Name, 35 chars, delimited by^
      ([^^]{0,28}.) # Address, 29 chars, delimited by^
      \?$ 
     @x', 
     $license, 
     $fields 
    ); 

    $state = $fields[1]; 
    $city = rtrim($fields[2], '^'); 
    $name = explode('$', rtrim($fields[3], '^')); 
    $address = explode('$', rtrim($fields[4], '^')); 

    echo "$license\n"; 
    echo "STATE: "; print_r($state); echo "\n"; 
    echo "CITY: "; print_r($city); echo "\n"; 
    echo "NAME: "; print_r($name); 
    echo "ADDRESS: "; print_r($address); 
    echo "\n"; 
} 

Выход:

CAMISSION HILLSSMITH$JOHN$JIM$JR^1147 SOMESTREET^ 
STATE: CA 
CITY: MISSION HILLS 
NAME: Array 
(
    [0] => SMITH 
    [1] => JOHN 
    [2] => JIM 
    [3] => JR 
) 
ADDRESS: Array 
(
    [0] => 1147 SOMESTREET 
) 

CALOS ANGELES^DOE$JOHN$CARL^14324 MAIN ST APT 5^ 
STATE: CA 
CITY: LOS ANGELES 
NAME: Array 
(
    [0] => DOE 
    [1] => JOHN 
    [2] => CARL 
) 
ADDRESS: Array 
(
    [0] => 14324 MAIN ST APT 5 
) 
+0

Джон, спасибо тебе за это. Я все еще пытаюсь заставить это работать. Regex не моя сильная сторона. Я должен был удалить «%» и «?» поскольку они не нужны. Мне просто нужно удалить эти символы из вашего регулярного выражения, чтобы заставить это работать? – John

+0

Да, вы можете удалить '%' с фронта и '\?' Со спины, если вы уже удалили их. –

+0

ОК, Джон, я удалил «%», а также «/?». но теперь я получаю пустой массив. Что я делаю не так? – John

3

Разве вы не задали этот вопрос несколько часов назад? Кто-то отправил регулярное выражение, которое обрабатывает случай, когда вы разделяете строки, которые либо разделены, либо исполняют ровно 13 символов: Help with a delimited string

Разве это не работает?

EDIT: Формат объясняется здесь: http://en.wikipedia.org/wiki/Magnetic_stripe_card#United_States_driver.27s_licenses

Для города, он говорит: "Field Separator - один символ (обычно '^') (отсутствует, если город достигает максимальную длину)". Таким образом, простое регулярное выражение может творить чудеса здесь. См. Пример, вы можете настроить его так, чтобы он соответствовал формату, как описано в этой записи.

EDIT: Хорошо, я сделаю снимок.

$str = "%CAMISSION HILLSSMITH$JOHN$JIM$JR^1147 SOMESTREET^?"; 
preg_match("/%(..)". 
      "([^\^]{1,13})\^?". 
      "([^\\\$]+)\\\$". 
      "([^\\\$]+)\\\$/", 
      $str, $m); 
$State = $m[1]; 
$City = $m[2]; 
$LastName = $m[3]; 
$FirstName = $m[4]; 

Как пример hwo вы можете пойти на него. В принципе, ([^\^]{1,13}) означает, что он попытается получить до 13 символов, которые не являются символами '^'. Как только это будет сделано, он будет потреблять символ «^», если он есть через \^?.

+0

Спасибо за ссылку. Да, это был я. Я попробовал код, который я дал кредит, но он не работает. Я получаю неправильные результаты. Ответ, который я принял, делает то же самое, что и в регулярном выражении. – John

+0

Вам нужно настроить его в формате - это не только 13 символов. См. Ссылку Википедии, которую я добавил. Формат четко определен, но это больше, чем просто «каждая запись - до 13 символов». – EboMike

+0

ОК, Эбо, еще раз спасибо. Я сделаю это. Можете ли вы подтвердить, что мне нужно сделать 100%? Я не очень силен в строковых функциях и даже меньше в регулярном выражении. – John

2

Работайте слева направо, имея дело с одним полем за раз.

сдирать ведущих%:

CAMISSION HILLSSMITH$JOHN$JIM$JR^1147 SOMESTREET^?

Возьмите первые 15 символов (. Первое поле не более 15 символов, верно?):

CAMISSION HILLS

Не содержит карет - это наше первое поле - следующее поле начинается с 16-го символа:

SMITH$JOHN$JIM$JR^1147 SOMESTREET^? (R1)

Я не знаю максимальную длину. этого поля - давайте предположим, что это 20. Возьмите первые 20 символов:

SMITH$JOHN$JIM$JR^11

Содержит каретку - итак, мы> 1 поле здесь.Возьмите чарс до каретки:

SMITH$JOHN$JIM$JR

... это наше следующее поле. Теперь возьмите строку из (R1) выше, начиная с (длиной поля предыдущего + 2) -го символом (+2, чтобы пропустить над ^)

1147 SOMESTREET^?

т.д.

+0

Спасибо. Первое поле - это состояние и всегда 2. Это легко. Второе поле - город. После этого у нас есть имя человека. Последнее поле - это весь адрес. Первое поле - 2 часа. Поле города - 13 символов. Поле имени - 35 символов, а адрес - 29 символов – John

+0

@John: Нет проблем - рад помочь. Подход, приведенный выше, хотя и не самый эффективный способ сделать это, помогает вам логически разбить его на управляемые куски - вы должны найти довольно простой способ выполнить синтаксический анализ в PHP таким образом. –

+1

и без регулярного выражения! http://xkcd.com/208/ – alexanderpas

0

Если бы это было Java , Я бы решил это с помощью регулярных выражений. Я знаю, что в PHP должно быть что-то еще?

Все перечисленные ограничения могут быть переведены в REGEX.

, например:

X{n,m}?  X, at least n but not more than m times 

можно использовать что-то вроде:

[^%\$\^]{1,13}[%\$\^] 

который гласит, «1-13 экземпляров любого символа не равны%, $ или^с последующим одним из тех же самых разделителей »

Когда я пишу регулярное выражение, я часто ссылаюсь на Java's great doc page. Вы также можете выполнять аккуратные трюки, такие как извлечение определенных совпадающих частей и вытягивание определенных слов. Опять же, я больше знаком с java, но PHP слишком зрелый язык не, чтобы иметь те же функции.

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

  • gMale
+0

gmale, спасибо за код. Я собираюсь попробовать это в ближайшее время. – John

Смежные вопросы