V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
css3
V2EX  ›  程序员

shell 如何提取文件中的指定内容

  •  
  •   css3 · 2019-04-02 11:52:25 +08:00 · 5650 次点击
    这是一个创建于 2060 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有这一样一个文件,有个需求,提取指定内容,如,想提取 red 这一组的 ip 出来,应该怎么用 shell 实现啊 :

    // hosts.txt
    [green]
    192.168.1.1
    
    [bule]
    192.168.1.123
    192.168.1.156
    
    [red]
    192.168.1.14
    192.168.1.231
    192.168.14.27
    
    [yellow]
    192.168.2.55
    192.168.13.23
    
    .....
    // 多组这样的内容
    
    
    第 1 条附言  ·  2019-04-02 12:24:03 +08:00
    每组的 ip 数量未知,不固定的
    第 2 条附言  ·  2019-04-02 12:55:12 +08:00
    各组的相对位置也未知,不固定
    25 条回复    2019-04-03 13:48:23 +08:00
    CallMeReznov
        1
    CallMeReznov  
       2019-04-02 11:58:28 +08:00
    j0hnj
        2
    j0hnj  
       2019-04-02 12:00:16 +08:00
    python3 -c "import configparser; config = configparser.ConfigParser(); config.read('hosts.txt'); print(config['red'])"
    jasonyang9
        3
    jasonyang9  
       2019-04-02 12:02:06 +08:00
    搜索关键字:linux ini style config parser
    css3
        4
    css3  
    OP
       2019-04-02 12:26:31 +08:00
    @j0hnj 执行后是这样啊,不是 ip
    <Section: red>😭
    pudgedoor
        5
    pudgedoor  
       2019-04-02 12:28:11 +08:00 via Android
    Awk 了解一下
    OscarUsingChen
        6
    OscarUsingChen  
       2019-04-02 12:33:00 +08:00
    shell? 那意思不能用 awk,不能用 grep,不能用 python?
    css3
        7
    css3  
    OP
       2019-04-02 12:39:20 +08:00 via iPhone
    @OscarUsingChen 可以啊
    taolu
        8
    taolu  
       2019-04-02 12:50:20 +08:00
    sed -n '/red/,/yellow/p' | sed -e 's/\[red\]//' -e 's/\[yellow\]//' -e '/^$/d'
    d0m2o08
        9
    d0m2o08  
       2019-04-02 12:52:51 +08:00
    [root@rac1 tmp]# cat 123
    [green]
    192.168.1.1

    [bule]
    192.168.1.123
    192.168.1.156

    [red]
    192.168.1.14
    192.168.1.231
    192.168.14.27

    [yellow]
    192.168.2.55
    192.168.13.23
    [root@rac1 tmp]# sed -n '/\[red\]/,/^$/p' 123
    [red]
    192.168.1.14
    192.168.1.231
    192.168.14.27

    [root@rac1 tmp]#
    taolu
        10
    taolu  
       2019-04-02 12:54:34 +08:00
    sed -n '/red/,/^$/p' | sed -e 's/\[red\]//' -e '/^$/d'
    修改了下
    OscarUsingChen
        12
    OscarUsingChen  
       2019-04-02 12:55:41 +08:00
    ^纯 bash,基本没有依赖。
    taolu
        13
    taolu  
       2019-04-02 12:56:05 +08:00
    @d0m2o08 #9 正好想到,没想到已经发了,哈哈😄
    d0m2o08
        14
    d0m2o08  
       2019-04-02 12:58:09 +08:00
    @taolu 666
    DiamondbacK
        15
    DiamondbacK  
       2019-04-02 13:09:54 +08:00
    不知道哪个是你想要的:

    sed -n '/^\[red\]$/,/^ *$/p' # 假定每组有空行分隔
    sed -n '/^\[red\]$/,/^ *$/{/^[^[]/p}'
    sed -n '/^\[red\]$/{:a;/^ *$/!{n;p;ba;}}'
    aver4vex
        16
    aver4vex  
       2019-04-02 13:21:26 +08:00
    按行读数据。碰到 [red] 之后就提取下方数据,直到碰到[开头的为止。没啥难度。
    sunnyadamm
        17
    sunnyadamm  
       2019-04-02 13:54:10 +08:00 via Android
    sed,awk 都可以,具体用法自己查
    sunnyadamm
        18
    sunnyadamm  
       2019-04-02 13:55:33 +08:00 via Android
    再看一下,如果 IP 都是 192.168 开头,你 grep 也可以啊。。。
    lululau
        19
    lululau  
       2019-04-02 14:08:38 +08:00
    既然 sed / (g)awk 都算 shell,那么这个算吗

    ruby -ne 'print if /^\[red\]$/../^$/'
    liwl
        20
    liwl  
       2019-04-02 17:20:00 +08:00
    @lululau sed 和 awk 不用装很多社区版都有,ruby 有环境?
    CallMeReznov
        21
    CallMeReznov  
       2019-04-02 20:30:35 +08:00
    @css3 #4
    楼主,shell 不熟,但是按照
    @j0hnj #2 给的 python 代码实际是可以解决你的问题的
    至于为什么没启用是少了个选项而已.
    代码如下
    https://gist.github.com/CallMeReznov/dd4f93bc36d72da8716a819fa0d4d59d
    我在 WINDOWS 上的 py3 上测试成功了
    ps1aniuge
        22
    ps1aniuge  
       2019-04-03 00:03:03 +08:00
    win,linux,通用的 powershell 代码,测试通过。

    ```
    $a = Get-Content -LiteralPath 'a:\pscode\TEMP_2019\temp141\aaa.txt' -raw
    [string[]]$b = '[red]'
    $c = '['

    $a.
    split($b,'none')[1].
    split($c)[0] -split "`n"
    ```
    zbinlin
        23
    zbinlin  
       2019-04-03 01:26:53 +08:00
    awk -v selected=red '
    /^\s*\[.+\]\s*$/ {
    split($0, keys, /\[|\]/);
    curr_key = keys[2];
    next
    }

    selected == curr_key && $0 != "" {
    print $0
    }' hosts.txt
    j0hnj
        24
    j0hnj  
       2019-04-03 12:41:20 +08:00
    @CallMeReznov #21 看这个输出应该是报错了吧,这个代码我随手写的,没有测试过。楼主的文件并不是合法的 ini 文件,所以并不能用 configparser 去解析。所以我比较好奇为啥楼主运行没报错,而是输出 <Section: red> …
    no1xsyzy
        25
    no1xsyzy  
       2019-04-03 13:48:23 +08:00
    awk 'BEGIN{K=0} K==1&&/^\d.+/{print $0} /^\[.+\]$/{K=0} /^\[red\]$/{K=1}'
    能够对 [red] 块多次出现的情况应对。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5873 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 02:11 · PVG 10:11 · LAX 18:11 · JFK 21:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.