Shell AWK,如何转义问号符号

时间:2019-10-22 23:48:37

标签: shell applescript

我正在尝试使用shell从url字符串中提取字符(在方法之间使用)。我一直坚持识别“?”角色...

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 :(得分:0)

如果您不希望使用? 字符,请使用\\\\?代替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"

通常要从awk中的命令行中转义特殊字符,您必须使用两个反斜杠,如下所示下面的示例 终端 输出

$ 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 命令中,您必须加倍使用反斜杠

答案 1 :(得分:0)

我猜(希望)您的代码段是较大的AppleScript的一部分,否则我的直接建议是将整个内容编写为shell脚本,实际上已经是这样。

我相信选择合适的工具来完成正确的工作,在这种情况下,shell脚本和AppleScripting都可以独立完成同样的事情,因此从一个方向调用另一个是非常懒惰和讨厌。但是,个人喜好在我们每个人喜欢如何编写脚本方面都起着重要的作用,因此,我将由您自己决定是否要采用我的任何一种方法,还是坚持使用自目前可用的内容

由于您的代码主要是bash脚本,因此我将从这里开始: awk 当然是一种非常强大的脚本语言,它可以完成很多很棒的文字。但这不是在这里完成工作的正确工具:感觉就像抓住武士刀来切面包;它无疑能够做到这一点,但是我认为它并不是以最优雅的方式使用的,所以最终您陷入了混乱。我主要是指正则表达式,这些正则表达式只有在应用到您提供的特定URL时才有用,并且使用单词部分来定位匹配,这是您要依赖的字符串的最后一个方面在。这是我的处理方式:

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

使用'^.*/|[?=&]'进行模式匹配有两个优点:

  1. 应该立即注意到,它不使用特定于您的URL的任何元素,因此可以与通常遵循某种格式的大量URL配合使用(我们可以很自信,例如,在子弹12345之前的正斜杠将是出现在URL中的最后一个斜杠,该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")和问号,这花费了444ms。好的,我可以肯定,您可以腾出444ms的时间来运行脚本,因此,我不建议它需要更快。但是,无论如何,使用^.*/|[?=&]可以将操作数量减少到57,并且花费了216ms。因此,我们模式中相对无害的更改意味着脚本完成了一半的工作,而速度却提高了两倍。为了进一步说明对性能的令人惊讶的影响,对正则表达式进行细微更改后得到的结果是,当我从模式的前面删除了插入符号(^)时(这不会影响它所匹配的内容,并返回相同的结果)最终结果),性能下降了400%,在901毫秒内进行匹配之前,需要进行209次文字比较。这几乎是整整一秒钟,因此它正在占用您开始注意到的时间长度。


我花了很多时间讨论bash方法,我将通过仅AppleScript的方法来探讨这个问题,这似乎让我觉得它不太合适,但是事实上,我会说,在这种情况下,这可能是一种更好的工具。 awk是武士刀,理想情况下,我们更喜欢没有的面包刀,但是AppleScript是牛排刀,通常有点cr脚,几乎没有那么锋利,但实际上最终会真正整洁的工作,不会造成混乱。

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的特定部分:

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"
相关问题