В сценарии, над которым я работаю, мне нужно очистить строку до нужного мне формата.
Структура каждой строки: (почтовый индекс, название улицы, номер, добавочный номер):
В конце концов последовал
Результирующая строка должна быть 4 цифры, 2 буквы, номер и, в случае расширения, за которым следует x, а также буква или цифра добавочного номера
Ниже приведены некоторые примеры:
Я начал с
echo "1019RXJavakade254" | awk '{print substr($0,0,6)}'
чтобы получить почтовый индекс и после этого я думаю, что мне следует использовать «печатное совпадение», но я не могу получить его прямо оттуда.
Строки передаются индивидуально и используются на следующем шаге скрипта. Первоначально они поступают из файла csv, но (комбинация) столбцов, из которых поступает строка, всегда различаются. Первая часть скрипта обрабатывает это и создает эту исходную строку. Результирующая строка будет помещена обратно в столбец, который я могу добавить в качестве последнего столбца в исходный файл csv.
Мне известно о проблемах, связанных с числами после первых 6 символов и наличием расширения. Поэтому, на мой взгляд, рабочий процесс должен быть примерно таким: первые 6 символов должны быть 4 цифрами, 2 буквами, если не общий результат, пустой. Пропустите символы 7 и 8 и возьмите первую группу цифр, которые вы встретите после символа 8, это номер, а все остальное после этого является расширением. Расширение никогда не начинается с цифры. Только в случае расширения между ними стоит х. В расширении не должно быть буквенно-цифровых символов.
Этого должно хватить на большую часть, у остальных будет задержка доставки :)
@kvantour Спасибо за ответ. Я немного изменил код, чтобы получить не заглавные буквы. Результатом является часть более крупного приложения, которое запускается без присмотра на Xserve здесь, в компании. Итак, код, который я использую сейчас, это
set KixCodeSourceClean to do shell script "echo " & KixCodeSource & " | awk '/^[0-9]{4}[a-zA-Z]{2}.+[0-9]+[- ].+$/{match(substr($0,8),/[0-9]+[- ].+$/);s=substr($0,7+RSTART,RLENGTH); sub(/[- ]/,\"x\",s);print substr($0,1,6)s;next} /^[0-9]{4}[a-zA-Z]{2}.+[0-9]+[a-zA-Z].*$/{match(substr($0,8),/[0-9]+[a-zA-Z].*$/);s=substr($0,7+RSTART,RLENGTH);match(s,/[0-9]+/);print substr($0,1,6)substr(s,1,RLENGTH)\"x\"substr(s,RLENGTH+1);next} /^[0-9]{4}[a-zA-Z]{2}.+[0-9]+$/{ match(substr($0,8),/[0-9]+$/);s=substr($0,7+RSTART);print substr($0,1,6)s;next}'"
Он работает отлично и представляет собой единственную строчку, которую я предпочитаю в данном случае. Я часто использую этот метод. Прыгать в Applescript и выходить из него и использовать оболочку unix для более быстрого решения задач.
Строки передаются индивидуально и используются на следующем шаге.
Проблемы возникают с такими именами, как "1066EC1eLouwesweg6-F"
Вам нужно уточнить расширение. Вы говорите, что это разделено «тире, пробелом или чем-то еще», но у меня такое чувство, что это «что-то еще» будет источником проблем.
@TomFenech Также не забывайте его предпоследний пример, который показывает расширение без чего-либо.
@Tom and Kvantour Мне известно о проблемах, связанных с числами после первых 6 символов и наличием расширения. Поэтому, на мой взгляд, рабочий процесс должен быть примерно таким: первые 6 символов должны быть 4 цифрами, 2 буквами, если не общий результат, пустой. Пропустите символы 7 и 8 и возьмите первую группу цифр, которые вы встретите после символа 8, это номер, а все остальное после этого является расширением. Расширение никогда не начинается с цифры. Только в случае расширения между ними стоит х. В расширении не должно быть буквенно-цифровых символов.
@ user6802941 Я предлагаю вам отредактировать эту информацию в своем вопросе, чтобы сделать ее как можно более ясной.
@JBVeenstra не забывайте Синт Витушолт 2е Лаан в Виндшотене и А в Оттоланде. Пропуск первых двух может не решить проблему.
{} для правильного форматирования (или отступ каждой строки на 4 символа вручную).





Некоторые требования для извлечения почтового индекса и расширения, поэтому конвейерные результаты для дополнительного sed можно развернуть здесь.
$ str = "1066EC1eLouwesweg6"
$ sed -r 's/(^[0-9]{4}[A-Z]{2})..[^0-9]*(.*)/\1\2/' <<< "$str" | sed 's/-/x/' | sed -r '/[^x]/ s/(.*[0-9]+)([A-Z]+$)/\1x\2/'
1066EC6
Краткое объяснение,
sed -r 's/(^[0-9]{4}[A-Z]{2})..[^0-9]*(.*)/\1\2/' <<< "$str": сначала отфильтровывает название улицы.sed 's/-/x/': замените '-' на 'x', если существуетsed -r '/[^x]/ s/(.*[0-9]+)([A-Z]+$)/\1x\2/': если результат до сих пор не существует "x", добавьте "x" между цифрами и алфавитами.Я имел в виду принцип исключения, в котором мы проверяем одну возможность за другой:
NNNNXXabc123efgMMM-SUF и NNNNXXabc123efgMMM SUFNNNNXXabc123efgMMMSUFNNNNXXabc123efgMMMПроблема, однако, в том, что SUF может быть чем угодно, а abc123efg - чем угодно. Как следствие, пример «1066EC1eLouwesweg6» будет соответствовать второму случаю.
Чтобы избежать этого, я подумал взглянуть на условия для названий улиц, но в Нидерландах это может быть что угодно:
')Таким образом, нет даже условия относительно длины названия улицы, за исключением того, что если оно состоит из одного символа, это буква.
Итак, это дало мне следующий AWK:
{gsub(/\r/,"",$0)} # removes `\r` if any
/^[0-9][0-9][0-9][0-9][A-Z][A-Z].+[0-9]+[- ].+$/{match(substr($0,8),/[0-9]+[- ].+$/);s=substr($0,7+RSTART,RLENGTH); sub(/[- ]/,"x",s);print substr($0,1,6)s;next}
/^[0-9][0-9][0-9][0-9][A-Z][A-Z].+[0-9]+[a-zA-Z].*$/{match(substr($0,8),/[0-9]+[a-zA-Z].*$/);s=substr($0,7+RSTART,RLENGTH);match(s,/[0-9]+/);print substr($0,1,6)substr(s,1,RLENGTH)"x"substr(s,RLENGTH+1);next}
/^[0-9][0-9][0-9][0-9][A-Z][A-Z].+[0-9]+$/{ match(substr($0,8),/[0-9]+$/);s=substr($0,7+RSTART);print substr($0,1,6)s;next}
И в этом входном файле:
1019RXJavakade254
1019PGBogortuin50
1079THEemsstraat34-II
1066EC1eLouwesweg6
1019LCKNSM-laan193
1019WZScheepstimmermanstraat74
2288EASirWinstonChurchillaan275-F126
1056HZMaartenHarpertszoonTrompstraat12-3hg
1092GRLaing'snekstraat15G
F-30700RueduLavoir1
Это дало мне следующий результат:
1019RX254
1019PG50
1079TH34xII
1066EC6
1019LC193
1019WZ74
2288EA275xF126
1056HZ12x3hg
1092GR15xG
Как вы заметили, последний не совпадает!
Однако я не могу заверить вас, что это сработает на 100%.
fun fact: In Ottoland, you can travel from A to B by crossing a bridge of 10m.
Это (с использованием GNU awk для 3-го аргумента для match() и gensub()) даст ожидаемый результат из предоставленных вами входных данных:
$ cat tst.awk
match($1,/^([0-9]{4}[[:alpha:]]{2})(..[^0-9]+)(.*)/,a) {
if ( ! sub(/[^[:alnum:]]/,"x",a[3]) ) {
a[3] = gensub(/([0-9])([[:alpha:]])/,"\\1x\\2",1,a[3])
}
}
{
tgt = (1 in a ? a[1] a[3] : "nothing")
print tgt, (tgt == $NF ? "succ" : "fail")
}
$ awk -f tst.awk file
1019RX254 succ
1019PG50 succ
1079TH34xII succ
1066EC6 succ
1019LC193 succ
1019WZ74 succ
2288EA275xF126 succ
1056HZ12x3hg succ
1092GR15xG succ
nothing succ
Это не удастся, если цифра может появиться в названии улицы где угодно, кроме первых двух символов.
Вышеупомянутое было выполнено для этого входного файла и печатает succ / fail после каждого результата в зависимости от того, соответствует ли результат ожидаемому результату из последнего поля входного файла:
$ cat file
1019RXJavakade254 -result: 1019RX254
1019PGBogortuin50 -result: 1019PG50
1079THEemsstraat34-II -result: 1079TH34xII
1066EC1eLouwesweg6 -result: 1066EC6
1019LCKNSM-laan193 -result: 1019LC193
1019WZScheepstimmermanstraat74 -result: 1019WZ74
2288EASirWinstonChurchillaan275-F126 -result: 2288EA275xF126
1056HZMaartenHarpertszoonTrompstraat12-3hg -result: 1056HZ12x3hg
1092GRLaing'snekstraat15G -result: 1092GR15xG
F-30700RueduLavoir1 -result: nothing
Эти строковые переменные передаются в ваш скрипт по отдельности или они берутся из файла сразу (например, каждая в отдельной строке)?