【问题标题】:Get string after a line with a certain word在包含某个单词的行之后获取字符串
【发布时间】:2018-09-19 13:50:40
【问题描述】:

对于 openwrt,我通常使用 UCI 来获取某些脚本的变量数据。类似的东西:

uci get /etc/config/network.lan.data

不幸的是,我没有发现 Linux 有类似的东西,但我相信 awk 或 sed 可以在不需要大量输出的情况下做到这一点。

一般来说,第一个字符串只是寻找第二个的参数

输入:

    ...

config 'wan'
    data 'a1 a2 a3'
    something 'words'

config 'lan'
    info 'words'
    data 'b1 b2 b3'
    something 'words'

config 'net'
    something 'words'
    info 'words'
    data 'c1 c2'

    ...

输出:

b1 b2 b3

--- 编辑:--

我相信有了这个表单的输入,脚本的功能会更广泛:

输入:

    ...

config something 'wan'
    something some_data 'a1 a2 a3'
    something 'words'

config something 'lan'
    something some_info 'words'
    something some_data 'b1 b2 b3'
    something 'words'

config something 'net'
    something 'words'
    something some_info 'words'
    something some_data 'c1 c2'

    ...

注意请求,这里有更好的解释:

1 - 查找带有 'lan' 的行(或者可能带有 config.*.'lan')

2 - 如果找到,则在以下行中搜索以单词结尾的数据(可能是 *.data)的第一行

3 - 打印此行''之间的内容

输出:

b1 b2 b3

什么是最好的解决方案?

感谢关注!

【问题讨论】:

  • 不够清楚,能否请您告诉我在 Input_file 中从何处执行搜索?请对此更加清楚。
  • 如果您假设我们知道 openwrt I usually use UCI 来说明您的要求,那么 YMMV。告诉我们输出b1 b2 b3 的标准是什么,因为有几种替代方案和几种可能的方法来实现解决方案(data 第二次出现?包含lan 的块?还有其他东西吗?),因此您可以选择不拘一格的答案到目前为止!
  • 1 - 搜索第一行有“lan”(或“something.*.'lan'”)的行; 2 - 如果在包含“日期”的第一行下方找到并打印 ' ' 之间的值

标签: string awk sed get next


【解决方案1】:

你可以使用类似的东西:

awk -v C="lan" -v F="data" '$1=="config" { gsub(/^[\47"]|[\47"]$/,"",$2); conf=$2; next } conf==C && $1==F { $1=""; gsub(/^ *[\47"]|[\47"]$/, ""); print }' YOURFILE

输入:

config 'wan'
    data 'a1 a2 a3'
    something 'words'

config 'lan'
    info 'words'
    data 'b1 b2 b3'
    something 'words'

config 'net'
    something 'words'
    info 'words'
    data 'c1 c2'    

输出:

b1 b2 b3

更新问题的方法略有不同:

awk -v C="lan" -v F="data" 'BEGIN { FS="\47"; REG=".*"F"[ \t]*" } $1~"config[ \t]" { conf=$2 } conf==C && $1~REG { print $2 }' YOURFILE

输入:

config something 'wan'
    something some_data 'a1 a2 a3'
    something 'words'

config something 'lan'
    something some_info 'words'
    something some_data 'b1 b2 b3'
    something 'words'

config something 'net'
    something 'words'
    something some_info 'words'
    something some_data 'c1 c2'

输出:

b1 b2 b3

【讨论】:

    【解决方案2】:

    使用 gnu sed

    猫 sedscript

    :A
    /^config/!d
    /lan/!d
    :B
    N
    s/.*\n//
    /^config/bA
    /.*data[^']*/!bB
    s///
    :C
    s/([^']*)(')([^']*.*)/\1\3/
    tC
    p
    bB
    

    你这样称呼它

    sed -nEf sedscript infile
    

    【讨论】:

      【解决方案3】:

      使用,您可以通过将RS 设置为空字符串来将每个部分视为一条记录,并将每行设置为一个字段,方法是将FS 设置为换行符。

      parse.awk

      BEGIN {
        RS = ""
        FS = "\n"
        q  = "'"      # Convenient definition of the quote character
      }
      
      $1 ~ q c q {
        for(i=2; i<=NF; i++) {
          if( $i ~ /^ *data / ) {
            split($i, a, q)
            print a[2]
          }
        }
      }
      

      像这样运行它:

      awk -f parse.awk -v c=lan dims
      

      输出:

      b1 b2 b3
      

      【讨论】:

        【解决方案4】:
        $ awk '
        BEGIN {
            RS=""                      # empty RS separates record by empty lines
            FS=" *\47[\n ]*"           # FS is a single quote surrounded by space and \n
        }
        match($0,"config" FS "lan") {  # if record has proper config line
            for(i=1;i<=NF;i+=2)        # iterate keys
                if($i=="data")         # if data found
                    print $(i+1)       # print its value
        }' file
        b1 b2 b3
        

        【讨论】:

        • 很漂亮,但它对数据进行了更多假设,例如以空行分隔的记录,字段值必须以单引号开头,只有单个字段值(会删除data 'b1 b2 b3' 'b4 b5'的一些数据)。
        • @AndriyMakukha 你准备好解决方案中的data 'b1 b2 b3' 'b4 b5'了吗?
        • 否,但由于我的解决方案只输出字段名称后的所有内容,仅修剪两边的引号,因此它会输出b1 b2 b3' 'b4 b5,这样更安全。
        • 你说的更多词是什么意思。请发布该请求的匹配数据。
        • 我用 .* in ##($0,"config.*" FS "lan")## 修改你的代码并为输入工作:config something 'lan' ###But i can' t 这样做 ###"if($i=="*.data")### :some_data 'b1 b2 b3'
        猜你喜欢
        • 1970-01-01
        • 2012-10-22
        • 1970-01-01
        • 2015-04-10
        • 2021-11-11
        • 1970-01-01
        • 2017-11-02
        • 2020-08-19
        • 1970-01-01
        相关资源
        最近更新 更多