【问题标题】:Regex match and print using awk/grep/sed/bash/vim使用 awk/grep/sed/bash/vim 进行正则表达式匹配和打印
【发布时间】:2017-04-13 01:40:08
【问题描述】:

我有一个文本文件,其中每一行都有以下结构

<six digit number>;; some text of arbitrary (non-zero) length<another six digit number>some other (possibly zero length) text

我只想从每行中提取成对的六位数字 例如,如果一行包含

234567;; some text with any number of arbitrary characters876352some other text

输出将是

234567;;876352

我使用 awk/grep/sed/bash/vim 尝试过的解决方案总数太多,无法在此处列出。以下是其中之一

#!/bin/bash

truncate --size 0 file.out
for line in "$(cat ../allwithpins)";
do
    echo $line | 'match($0, /[0123456789]{6}/, ary) {print ary[0], ary[1]}' >> file.out
    # echo $line
    # if [[ $line =~ [0123456789]{6} ]];
    # then
    #     echo ${BASH_REMATCH[$1]}
    #     #echo ${BASH_REMATCH[$1]}
    #     #echo ${BASH_REMATCH[$2]}
    # fi;
done

【问题讨论】:

  • 数字之间的文字可以包含数字吗?
  • @nu11p01n73R 是的,文本中可以有数字和标点符号
  • 匹配是否应该是 awk 命令?

标签: regex bash awk sed grep


【解决方案1】:
sed -r 's/^([0-9]{6};;).*([0-9]{6}).*/\1 \2/g' inputfile
234567;;876352

注意:如果您希望输出不被;; 分隔:

sed -r 's/^([0-9]{6}).*([0-9]{6}).*/\1 \2/g' inputfile

在这里,我们在这里捕获() 中的文本组,然后使用\1\2 ...\n 引用它们。所以第一个(``) 的内容可以稍后使用\1 等来引用。

【讨论】:

  • 感谢您的帮助。但是这个解决方案也有与其他解决方案相同的问题。当第二个 6 位数字序列后跟一些其他文本时,它会失败
  • 我在 vim 中使用 regex replace 替换了所有 7 位或更多位的序列。然后尝试了您的解决方案,它给出了完美的结果。谢谢
【解决方案2】:

使用awk的另一种解决方案

awk -F"[^0-9;]" '{print $1$(NF)}'
  • -F"[^0-9;]" 将字段分隔符设置为除数字以外的任何内容,;

  • print $1$(NF) 为每个输入行打印由指定分隔符分隔的第一个和最后一个字段。

    NF 是字段总数,因此$(NF) 将是最后一个字段。


示例

$ echo "234567;; some text with any 123 number of arbitrary characters876352" | awk -F"[^0-9;]" '{print $1$(NF)}'
234567;;876352

编辑

如果您想对位数等进行更多检查,正则表达式比较可以帮助您。

示例

$ awk -F"[^0-9;]" '$1 ~ /[0-9]{6};;/ && $0 ~ /[^0-9][0-9]{6}$/{print $1$(NF)}' file
234567;;876352
234567;;876352

$ cat file
234567;; some text with any number of arbitrary characters876352
234567;; some text with any number of arbitrary characters876352iaasdfadf
234567;; some text with any number of arbitrary characters876352
234567;; some text with any number of arbitrary characters8763
234567;; some text with any number of arbitrary characters876352iaasdfadf0987654321
  • $1 ~ /[0-9]{6};;/ 检查第一个字段是否包含 6 位数字,后跟 ;;

  • $0 ~ /[^0-9][0-9]{6}$ 检查输入行是否以 6 位数字结尾。 [^0-9] 检查 6 位数字之前是否没有其他数字。

【讨论】:

  • 谢谢。此解决方案有效,除非第二个 6 位数字序列后跟一些其他文本。如问题中所述,它可能并不总是最后一个字段。此外,在最初发布的脚本中使用此解决方案,会生成一个只有一行的输出文件。
  • @sid-m 如果您想对输入行进行更多检查,可以在 {print } 之前添加检查。我添加了一个编辑。希望对你有帮助
  • 谢谢。非常感谢您的帮助。这个解决方案几乎奏效了。但事实证明,某些行恰好在第二个 6 位序列之后包含一个 10 位序列,例如 234567;; some text with any number of arbitrary characters876352iaasdfadf0987654321,并且该命令最终打印了 10 位序列
  • @sid-m 哎呀,这是我的错误。已更正。将解释它的作用
  • 谢谢,我很抱歉一直唠叨。可能是我很难清楚地解释我的要求。但是即使不在行尾,也需要提取六位序列。后面可能还有其他字符。无论如何,这非常接近所以赞成:)
【解决方案3】:

使用 sed,删除除数字和分号之外的所有字符:

sed 's/[^0-9;]//g' <<< "234567;; some text with any number of arbitrary characters876352some other text"
234567;;876352

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 2011-07-29
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多