Bash 正则表达式提取从第 2 次出现的特定字符到行尾的所有文本
Bash Regex extract all text from 2nd occurence of specific character until end of line
我有以下字符串:
text/:some_random_text:text_i_w4nt_to:k33p.until_th3_end_1
text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1
用正则表达式,我要提取:
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
我已经尝试使用 regex101.com 以下表达式:([^:]+)(?::[^:]+){1}$
并且有效(仅适用于第一个字符串)
但是如果我尝试 bash,它不会
echo "text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1" | sed -n "/([^:]+)(?::[^:]+){1}$/p"
使用sed
$ sed s'|\([^:]*:\)\{2\}\(.*\)$||' input_file
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
或
$ sed s'|\([^:]*:\)\{2\}||' input_file
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
使用 cut
没有任何正则表达式会容易得多:
cut -d: -f3- file
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
sed
不支持非捕获组 (?:
,您必须转义 \(
\)
\{
\}
和 \+
您可以从字符串的开头重复出现 2 次 :
并将其替换为空字符串。
sed 's/^\([^:]\+:\)\{2\}//' file
或使用 sed -E
扩展正则表达式:
sed -E 's/^([^:]+:){2}//' file
输出
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
没有理由将 sed
或其他外部程序拖入其中;只需使用 bash 的内置正则表达式匹配:
#!/usr/bin/env bash
strings=(text/:some_random_text:text_i_w4nt_to:k33p.until_th3_end_1
text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1)
for s in "${strings[@]}"; do
[[ $s =~ ^([^:]*:){2}(.*) ]] && printf "%s\n" "${BASH_REMATCH[2]}"
done
哎呀,在 bash:
中不需要正则表达式
printf "%s\n" "${s#*:*:}"
awk
string='ext/:some_random_text:text_i_w4nt_to:k33p.until_th3_end_1
text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1'
awk -vFS=: -vOFS=: '{=="";gsub(/^::/,"")}1' <<<"$string"
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
绝对不需要使用任何需要 regex-backreferences
的东西,因为正则表达式锚定就在行首:
mawk ++NF OFS= FS='^[^:]*:[^:]*:'
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
我有以下字符串:
text/:some_random_text:text_i_w4nt_to:k33p.until_th3_end_1
text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1
用正则表达式,我要提取:
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
我已经尝试使用 regex101.com 以下表达式:([^:]+)(?::[^:]+){1}$
并且有效(仅适用于第一个字符串)
但是如果我尝试 bash,它不会
echo "text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1" | sed -n "/([^:]+)(?::[^:]+){1}$/p"
使用sed
$ sed s'|\([^:]*:\)\{2\}\(.*\)$||' input_file
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
或
$ sed s'|\([^:]*:\)\{2\}||' input_file
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
使用 cut
没有任何正则表达式会容易得多:
cut -d: -f3- file
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
sed
不支持非捕获组 (?:
,您必须转义 \(
\)
\{
\}
和 \+
您可以从字符串的开头重复出现 2 次 :
并将其替换为空字符串。
sed 's/^\([^:]\+:\)\{2\}//' file
或使用 sed -E
扩展正则表达式:
sed -E 's/^([^:]+:){2}//' file
输出
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
没有理由将 sed
或其他外部程序拖入其中;只需使用 bash 的内置正则表达式匹配:
#!/usr/bin/env bash
strings=(text/:some_random_text:text_i_w4nt_to:k33p.until_th3_end_1
text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1)
for s in "${strings[@]}"; do
[[ $s =~ ^([^:]*:){2}(.*) ]] && printf "%s\n" "${BASH_REMATCH[2]}"
done
哎呀,在 bash:
中不需要正则表达式printf "%s\n" "${s#*:*:}"
awk
string='ext/:some_random_text:text_i_w4nt_to:k33p.until_th3_end_1
text/:some_random_text:text_i_w4nt_to::k33p.until_th3_end_1'
awk -vFS=: -vOFS=: '{=="";gsub(/^::/,"")}1' <<<"$string"
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1
绝对不需要使用任何需要 regex-backreferences
的东西,因为正则表达式锚定就在行首:
mawk ++NF OFS= FS='^[^:]*:[^:]*:'
text_i_w4nt_to:k33p.until_th3_end_1
text_i_w4nt_to::k33p.until_th3_end_1