2

我在 Linux shell 中有一个字符串。该字符串中包含下划线。

我想从字符串中提取一个子字符串。

我想在第三次出现下划线后提取子字符串,从字符串的末尾开始计算。

file_name='email_Tracking_export_history_2018_08_15'
string_name="${file_name#*_*_*_}"
file_name2='email_Tracking_export_2018_08_15'
string_name2="${file_name2#*_*_*_}"

echo "$string_name"
echo "$string_name2"

结果

history_2018_08_15
2018_08_15

如您所见,string_name="${file_name#*_*_*_}"无法正常工作。

期望的结果:

2018_08_15
2018_08_15

我怎样才能达到我想要的结果?

4

6 回答 6

3

您可以一步完成,但有点复杂。设置文件名后

file_name='email_Tracking_export_history_2018_08_15'

我们得到的子字符串包含除了我们最终想要的内容之外的所有内容:

$ echo "${file_name%_*_*_*}"
email_Tracking_export_history

这几乎就是我们想要的,只是少了一个下划线,所以我们补充一下:

$ echo "${file_name%_*_*_*}_"
email_Tracking_export_history_

现在我们知道我们必须从字符串的开头删除什么并将其插入到扩展中:${word#pattern}

$ echo "${file_name#"${file_name%_*_*_*}_"}"
2018_08_15

或者我们将其分配给一个变量以供进一步使用:

string_name=${file_name#"${file_name%_*_*_*}_"}
              └───┬───┘ │  └───┬───┘ └─┬──┘  │
             outer word │  inner word  └────────inner pattern
                        └───outer pattern────┘

与第二个字符串类似。

于 2018-09-10T04:15:55.770 回答
0

使用(大多数)sed 和 BRE:

sed 's/.*_\([^_]*\(_[^_]*\)\{2\}\)$/\1/' <<< "$file_name"
2018_08_15

使用 GNU sed 和 ERE:

sed -r 's/.*_([^_]*(_[^_]*){2})$/\1/' <<< "$file_name"
2018_08_15
于 2018-09-10T06:07:58.017 回答
0

使用临时变量:

file_name='email_Tracking_export_history_2018_08_15'
temp="${file_name%_*_*_*}"
string_name="${file_name/${temp}_}"
file_name2='email_Tracking_export_2018_08_15'
temp="${file_name2%_*_*_*}"
string_name2="${file_name2/${temp}_}"

echo "$string_name"
echo "$string_name2"
于 2018-09-10T03:38:39.930 回答
0

如何在 bash 中使用正则表达式:

#!/bin/bash

# Extract substring from string after 3rd occurrence in reverse
function extract() {
    if [[ "$1" =~ _([^_]+_[^_]+_[^_]+$) ]]; then
        echo "${BASH_REMATCH[1]}"
    fi
}

file_name='email_Tracking_export_history_2018_08_15'
string_name=$(extract $file_name)

file_name2='email_Tracking_export_2018_08_15'
string_name2=$(extract $file_name2)

echo "$string_name"
echo "$string_name2"
于 2018-09-10T04:01:05.527 回答
0

即使是expr字符串匹配也已经被禁止进入最深的地狱?:

$ expr "$file_name" : '.*_\([^_]*_[^_]*_[^_]*\)'
2018_08_15
$ expr "$file_name2" : '.*_\([^_]*_[^_]*_[^_]*\)'
2018_08_15

来自https://www.tldp.org/LDP/abs/html/string-manipulation.html

expr "$string" : '.*\($substring\)'

    Extracts $substring at end of $string, where $substring is a regular expression.
于 2018-09-10T06:56:30.910 回答
0
% echo $file_name | rev | cut -f1-3 -d'_' | rev
2018_08_15
% echo $file_name2 | rev | cut -f1-3 -d'_' | rev
2018_08_15

rev反转字符串,以便轻松计算 3 个下划线的出现次数。然后将要提取的字符串部分反转回来。

于 2018-09-10T05:56:39.223 回答