Shell awk, как избежать знака вопроса - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь извлечь символы (используя подходы) из строки URL, используя shell. Я застрял в определении "?"символ ...

set sample to "https://someaddress.com/path/subpath/12345?userId=523"
set extract to do shell script "awk -F 'subpath/|userId' '{print $2}'<<<" & quoted form of sample

... это будет работать, но, очевидно, возвращает "12345?". Как мне также исключить «?». "\?"не делал это

Ответы [ 2 ]

0 голосов
/ 28 октября 2019

Я предполагаю (надеюсь), что ваш фрагмент является частью более крупного AppleScript, в противном случае моим непосредственным предложением было бы написать все это в виде сценария оболочки, что по сути уже есть.

Я считаю,при выборе правильного инструмента для правильной работы , и в этом случае и сценарии оболочки, и сценарий AppleScripting могут делать это одинаково хорошо самостоятельно, поэтому вызов из одного в другой довольно ленив и утомителен. Но личный вкус играет большую роль в том, как нам нравится писать наши сценарии, поэтому я оставлю вам решать, предпочитаете ли вы использовать какой-либо из моих методов или придерживаться того, что у вас есть, так как он сейчас работает.

Поскольку ваш код в основном представляет собой скрипт bash, я начну с него: awk, конечно, очень мощный язык сценариев сам по себе, и он может многоевеликих вещей с текстом. Но это не правильный инструмент для работы здесь: это похоже на то, чтобы схватить катану, чтобы нарезать немного хлеба;это, несомненно, способно сделать это, но я не думаю, что оно использовалось самым изящным образом, так что вы оказались в беспорядке. Я в основном ссылаюсь на регулярные выражения, которые привязаны к тому, чтобы быть полезными только применительно к указанному вами URL-адресу, и использую части слова для нацеливания на соответствие, что является последним аспектом строки, на которую вы хотите положитьсяна. Вот как я бы это сделал:

$ awk -F '^.*/|[?=&]' '{ print $2,$3,$4; }' <<< https://someaddress.com/path/subpath/12345?userId=523
12345 userId 523

Использование '^.*/|[?=&]' для сопоставления с образцом имеет несколько преимуществ:

  1. Следует сразу заметить, что это не 't использовать любые элементы, специфичные для вашего URL, и, как таковые, будут работать с огромным диапазоном URL, которые обычно придерживаются определенного формата (например, мы можем быть достаточно уверены, что прямой слеш, непосредственно предшествующий слагу 12345, будетбыть последним, который появляется в URL-адресе, который правильно сформирован и правильно закодирован, как любой другой, который следует после него, должен быть в процентах).

  2. Будем надеяться, что вы будете приятно удивлены отсутствием обратной косой черты, которая продолжает пытаться избежать двойных действий, что является одним из недостатков сценариев на одном языке и вызова другого. , и оба требуют, чтобы строка была экранирована специально для них, даже если она уже была экранирована один раз. Фактически мне удалось свести общее количество обратных косых черт к нулю, так как мое регулярное выражение не содержит ничего, что нужно экранировать. Вот тот же сценарий, встроенный в AppleScript, чтобы вы могли посмотреть и запустить его, чтобы убедиться, что он работает так:

    set www to "https://someaddress.com/path/subpath/12345?userId=523"
    set cmd to "awk -F '^.*/|[?=]' '{ print $2,$3,$4; }' <<<"
    do shell script cmd & www's quoted form
        --> "12345 userId 523"
    
  3. Последнее преимущество, которое будет полезно для некоторыхи не для других - это улучшенная эффективность и скорость регулярного выражения, с которым я столкнулся, когда сравнивал с вашим. Людям не всегда приходит в голову, что сопоставление регулярных выражений представляет собой сложный, интенсивный и достаточно дорогой набор операций, которые нужно выполнять, и вдумчиво подходить к их построению - в более жестких ситуациях, чем это, конечно,--- сделать большую разницу в том, насколько быстрым является сценарий. Для использования шаблона subpath/|\? необходимо выполнить 107 сравнений текста, чтобы сопоставить слаг ("subpath") и знак вопроса, который занял 444 мс. ОК, я вполне уверен, что вы можете сэкономить 444 мсек для запуска скрипта, конечно, поэтому я не предполагаю, что он должен быть быстрее. Но, в любом случае, использование ^.*/|[?=&] сократило количество операций до 57 и заняло 216 мс. Таким образом, относительно безобидное изменение в нашем шаблоне означает, что скрипт выполняет половину работы, и поэтому он делал это вдвое быстрее. Чтобы дополнительно проиллюстрировать удивительное влияние на производительность, результаты незначительного изменения регулярного выражения, когда я удалил каретку (^) из передней части моего шаблона (который не влияет на то, что он соответствует, и возвращает идентичные конечные результаты)), производительность упала на 400%, что потребовало 209 сравнений текста перед выполнением совпадений за 901 мс. Это почти целая секунда, и поэтому вы начинаете замечать отрезок времени.


Потратив много слов на обсуждение метода bash, я расскажу о методе только для AppleScript, и мне будет казаться, что я делаюриторизацию его как менее подходящего, но на самом деле я бы сказал, чтоэто, вероятно, в этой ситуации --- лучший инструмент для этой работы. awk - это катана, и в идеале мы предпочли бы хлебный нож, которого у нас нет, но AppleScript - это нож для стейка, который часто немного дрянной, далеко не такой острый, но на самом деле в конечном итоге делает действительноаккуратная работа без создания беспорядка.

set www to "https://someaddress.com/path/subpath/12345?userId=523"
set my text item delimiters to {"/", "?"}
return the text items of www
--> {"https:", "", "someaddress.com", "path", "subpath", "12345", "userId=523"}

Как и прежде, не имеет значения, что такое конкретный URL, поскольку он будет делать то же самое с любым правильно сформированным URL. Поскольку слаг находится перед последней косой чертой, встречающейся в URL, и за единственным вопросительным знаком, который должен отображаться в одном, он всегда будет располагаться вторым в списке компонентов, на которые этот AppleScript разбиваетURL довольно приятно. Таким образом, конкретная часть URL, которую вы хотите, будет возвращена из этого сценария:

set www to "https://someaddress.com/path/subpath/12345?userId=523"
set my text item delimiters to {"/", "?"}
set slug to text item -2 of www
--> "12345"
0 голосов
/ 23 октября 2019

Если вы не хотите, чтобы символ ? , затем используйте \\\\? вместо userId для значения опции -F , например, использовать -F 'subpath/|\\\\? вместо -F 'subpath/|userId':

set sample to "https://someaddress.com/path/subpath/12345?userId=523"
set extract to do shell script "awk -F 'subpath/|\\\\?' '{print $2}'<<<" & quoted form of sample
    --> "12345"

Обычно для экранирования специального символа из командной строки inawk вы должны использовать две обратных косых черты , как показано в примере Terminal output ниже:

$ awk -F 'subpath/|\?' '{print $2}'<<<'https://someaddress.com/path/subpath/12345?userId=523'
awk: illegal primary in regular expression subpath/|? at 
 input record number 1, file 
 source line number 1
$ awk -F 'subpath/|\\?' '{print $2}'<<<'https://someaddress.com/path/subpath/12345?userId=523'
12345
$

Однако в команде ApplesScript do shell script необходимо удвоить обратную косую черту .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...