【问题标题】:How to split a string or file that may be delimited by a combination of comments and spaces, tabs, newlines, commas, or other characters如何拆分可能由注释和空格、制表符、换行符、逗号或其他字符的组合分隔的字符串或文件
【发布时间】:2014-01-27 11:17:26
【问题描述】:

如果文件:list.txt 包含像这样非常丑陋的数据:

aaaa 
#bbbb
cccc, dddd; eeee
 ffff;
    #gggg hhhh
iiii

jjjj,kkkk ;llll;mmmm
nnnn

我们如何使用 bash 脚本解析/拆分该文件,不包括注释行,用所有逗号、分号和所有空格(包括制表符、空格和换行符和回车符)分隔它?

【问题讨论】:

    标签: regex bash shell parsing whitespace


    【解决方案1】:

    可以通过以下代码完成:

    #!/bin/bash
    ### read file:
    file="list.txt"
    
    IFSO=$IFS
    IFS=$'\r\n'
    while read line; do
        ### skip lines that begin with a "#" or "<whitespace>#"
        match_pattern="^\s*#"
        if [[ "$line" =~ $match_pattern ]];
            then 
            continue
        fi
    
        ### replace semicolons and commas with a space everywhere...
        temp_line=(${line//[;|,]/ })
    
        ### splitting the line at whitespaces requires IFS to be set back to default 
        ### and then back before we get to the next line.
        IFS=$IFSO
        split_line_arr=($temp_line)
        IFS=$'\r\n'
        ### push each word in the split_line_arr onto the final array
        for word in ${split_line_arr[*]}; do
                array+=(${word})
        done
    done < $file
    
    echo "Array items:"
    for item in ${array[*]} ; do
        printf "   %s\n" $item
    done
    

    这不是作为问题提出的,而是其他人在回答其他相关问题时所触及的问题的更好解决方案。这里唯一的一点是,其他问题/解决方案并没有真正解决当字符串由空格、字符和 cmets 组合分隔时如何拆分字符串;这是一种同时解决所有三个问题的解决方案...

    相关问题:

    How to split one string into multiple strings separated by at least one space in bash shell?

    How do I split a string on a delimiter in Bash?

    补充说明:

    为什么在其他脚本语言更适合拆分时使用 bash?例如,与 perl 程序相比,bash 脚本在从基本的 upstart 或 cron (sh) shell 运行时更有可能拥有所需的所有库。在这些情况下,通常需要一个参数列表,我们应该期待维护这些列表的人最坏的情况......

    希望这篇文章能在未来为 bash 新手(包括我)节省大量时间......祝你好运!

    【讨论】:

      【解决方案2】:

      如果你的系统上有 Ruby

      File.open("file").each_line do |line|
        next if line[/^\s*#/]
        puts line.split(/\s+|[;,]/).reject{|c|c.empty?}  
      end
      

      输出

      # ruby test.rb 
      aaaa
      cccc
      dddd
      eeee
      ffff
      iiii
      jjjj
      kkkk
      llll
      mmmm
      nnnn
      

      【讨论】:

        【解决方案3】:

        使用 shell 命令:

        grep -v "^[ |\t]*#" file|tr ";," "\n"|awk '$1=$1'
        

        【讨论】:

        • 你能让你的答案更具描述性吗?例如,解释它为什么起作用,每个论点代表什么等。这将使您的答案对未来的读者更有价值,并有助于教授 OP。
        • 不知道你对哪些部分有疑问,grep、tr、awk都是流行的shell命令,我不是来教的。如果他们想学习,人们可以在 google 中搜索大量样本来理解这些命令。为什么我们需要把他们当婴儿对待?
        • 这是一个不错的技巧,但我会这样写以将其放入可用的数组中: array=`grep -v "[^ |\t]*#" list.txt|tr ";," "\n"|awk '$1=$1'` 现在我将尝试解释它是如何工作的: grep 命令返回不匹配导致 # 字符的空白注释模式的所有行。然后 tr 命令交换“;”的所有实例或 "," 换行。 awk 命令是一个绝妙的技巧,可以从行中删除前导和尾随空格。因此,您将获得所需的数据...
        【解决方案4】:

        sed 's/[# \t,]/REPLACEMENT/g' input.txt

        • 上述命令将注释字符 ('#')、空格 (' ')、制表符 ('\t') 和逗号 (',') 替换为任意字符串 ('REPLACEMENT')

        • 替换换行符,可以试试:

        sed 's/[# \t,]/replacement/g' input.txt | tr '\n' 'REPLACEMENT'

        【讨论】:

        • 如果你想忽略 cmets,试试$ YOUR-CMD-HERE | grep -v '^#'。这将忽略以'#' 开头的行
        猜你喜欢
        • 2016-10-19
        • 2018-04-27
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多