【问题标题】:Bash expr index commandBash expr 索引命令
【发布时间】:2014-02-11 07:10:14
【问题描述】:

我正在尝试使用 Bash 'expr index" 获取索引位置。

例如

$ echo `expr index "Info.out.2014-02-08:INFO|SID:sXfzRjbmKbwX7jyaW1sog7n|Browser[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0]" Mozilla`

我正在尝试获取单词“Mozilla”的索引位置,然后使用索引值获取子字符串。

我得到的结果是4。是Info之后的时间导致问题吗?我该如何解决这个问题?

我遵循了高级 Bash 脚本指南 www.tldp.org/LDP/abs/html/。请参见表 B-5 部分。字符串操作

expr index "$string" $substring $substring* 中匹配的第一个字符在 $string 中的数字位置 [0 如果不匹配,第一个字符计为位置 1]

我尝试了一些简单的方法,它确实有效。

我在 cygwin 中运行 bash。

$ ./bash --version
GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

谢谢。

【问题讨论】:

  • 其实这是独立于bash的,因为expr是一个可以从任何shell运行的独立程序。
  • 您的实际目标是什么?也就是说,一旦你得到了索引,你想检索它之后的所有东西吗?之前呢?对于任何这些情况,根本不需要使用索引——一个简单的 PE 表达式就可以匹配你真正关心的内容。
  • 顺便说一句——ABS 是一个很差的参考;在 freenode 的 #bash 中,我们经常不得不帮助人们改掉他们从中养成的坏习惯。 mywiki.wooledge.org/BashGuidemywiki.wooledge.org/BashFAQ 是更好的起点。

标签: bash


【解决方案1】:

一般来说,除非您有充分的理由,否则您不应该使用 expr index

例如,假设您想获取浏览器名称。

s="Info.out.2014-02-08:INFO|SID:sXfzRjbmKbwX7jyaW1sog7n|Browser[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0]"

# strip everything up to and including the first instance of 'Browser['
browser="${s#*Browser[}"

# strip everything after the first ']', again, inclusive
browser="${browser%%]*}"

# ...and show the result...
echo "$browser"

这将返回:

Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0

如果你真的确实想知道Mozilla前面有多少个字符,那么你也可以这样做:

s="Info.out.2014-02-08:INFO|SID:sXfzRjbmKbwX7jyaW1sog7n|Browser[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0]"

# strip everything after the first instance of 'Mozilla'
prefix=${s%%Mozilla*}

# count number of characters in the string
index=${#prefix}

# ...and show the result...
echo "$index"

这应该返回61

有关上述示例的“为什么”和“如何”,请参阅BashFAQ #73


相比之下,要按| 分隔符进行拆分,我个人会选择使用read,如BashFAQ #1 中所述:

s="Info.out.2014-02-08:INFO|SID:sXfzRjbmKbwX7jyaW1sog7n|Browser[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0]"
IFS='|' read -r _ _ browser _
echo "$browser"

...会发出...

Browser[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0]

【讨论】:

  • 感谢 Charles 的帮助,我查看了您提供的文档,关于 bash 陷阱的部分非常有用。
【解决方案2】:

expr index 命令搜索您的第一个字符串,查找第二个字符串中第一次出现的任何字符。在这种情况下,它识别出字符“Mozilla”中的“o”与“Info.out...”中的第 4 个字符匹配

这用这个作为测试看看会发生什么。它将返回 4 作为 'd' 的第一个匹配项:

echo `expr index "abcdefghijklmnopqrstuvwxyz" xyzd`

这个应该做你想做的:

echo "Info.out.2014-02-08:INFO|SID:sXfzRjbmKbwX7jyaW1sog7n|Browser[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0]" | grep -o -b Mozilla

echo 将您的字符串放入标准输出,因此可以通过管道将其输入 grep。

-b 打印显示的字符串的字节偏移量。

-o 确保只打印匹配的部分。

【讨论】:

    【解决方案3】:

    GNU expr 不匹配使用 index 的子字符串;相反,它从第一个字符串中的第二个字符串中查找第一次出现的任何字符。您的示例返回 4,因为字符串的第 4 个字符是“o”,即在“Info.out...”中找到的“Mozilla”中的第一个字符。

    bashexpr 中都没有这种内置函数,但是您可以通过首先从原始字符串中删除子字符串及其后面的所有内容,然后计算来间接获取给定子字符串的索引剩余长度。

    string="Info.out..."
    substring=Mozilla
    tmp=${string%%$substring*}
    index=${#tmp}
    

    【讨论】:

    • 谢谢,它只匹配字符。那么,bash 有没有 substring 函数呢?
    • @g5thomas,“子字符串函数”是什么意思? Bash 确实可以让您获取子字符串,无论是我的索引还是模式匹配,但不,这样做不涉及函数。
    • 感谢您的解释。现在更清楚需要做什么了。
    猜你喜欢
    • 1970-01-01
    • 2015-10-16
    • 2013-10-09
    • 2011-06-14
    • 2018-04-01
    • 2019-02-07
    • 1970-01-01
    • 2021-06-03
    相关资源
    最近更新 更多