【问题标题】:Reading lines in a file and avoiding lines with # with Bash使用 Bash 读取文件中的行并避免使用 # 行
【发布时间】:2012-01-02 00:22:33
【问题描述】:

我试过了:

file="myfile"
while read -r line
do
    [[ $line = \#* ]] && continue
    "address=\$line\127.0.0.1"
done < "$file"

此代码不会避免以 cmets 开头的行。即使我没有任何 cmets,dnsmasq 也会告诉我有错误。

它将是一个dnsmasq conf 文件,它将像这样读取和插入域名:address=\mydomain.com\127.0.0.1


编辑:1

输入文件:

domain1.com
domain2.com
domain3.com
#domain4.com
domain5.com

输出应该是:

address=/domain1.com/127.0.0.1
address=/domain2.com/127.0.0.1
address=/domain3.com/127.0.0.1
address=/domain5.com/127.0.0.1

我会将脚本放到 /etc/dnsmasq.d/ 目录中,以便dnsmaq.conf 可以在dnsmasq 启动时处理它。

【问题讨论】:

    标签: bash loops comments


    【解决方案1】:

    跳过以# 开头的行

    grep -v '^#' myfile | while read -r file ; do
        ...
    done
    

    根据需要修改grep 命令,例如,跳过以空格和# 字符开头的行。

    【讨论】:

    • 我不是反对者,但也许他们更喜欢显式子shell而不是隐式子shell?如:while IFS= read -r TI; do echo "${TI}"; done &lt; &lt;(grep -v '#' ./items)
    • 这个比原来的答案快。因为读取整个文件并执行 grep 比较慢。
    【解决方案2】:

    使用[[ "$line" = "\#*" ]]更安全

    顺便说一句,address="\\${line}\\127.0.0.1"

    UPD

    如果我的理解正确,您需要将每个未注释的域更改为 address=\domain\127.0.0.1。使用sed 可以快速轻松地完成,在 bash-program 中不需要。

    $> cat ./text
    domain1.com
    domain2.com
    domain3.com
    #domain4.com
    domain5.com
    
    $> sed -r -e 's/(^[^#]*$)/address=\/\1\/127.0.0.1/g' ./text2
    address=/domain1.com/127.0.0.1
    address=/domain2.com/127.0.0.1
    address=/domain3.com/127.0.0.1
    #domain4.com
    address=/domain5.com/127.0.0.1
    

    如果您需要删除注释行,sed 也可以使用 /matched_line/d 完成此操作

    $> sed -r -e 's/(^[^#]*$)/address=\/\1\/127.0.0.1/g; /^#.*$/d' ./text2 
    address=/domain1.com/127.0.0.1
    address=/domain2.com/127.0.0.1
    address=/domain3.com/127.0.0.1
    address=/domain5.com/127.0.0.1
    

    UPD2:如果你想在 bash 脚本中做所有这些事情,这里是你的代码修改:

    file="./text2"
    while read -r line; do
        [[ "$line" =~ ^#.*$ ]] && continue
        echo "address=/${line}/127.0.0.1"
    done < "$file"
    

    它的输出:

    address=/domain1.com/127.0.0.1
    address=/domain2.com/127.0.0.1
    address=/domain3.com/127.0.0.1
    address=/domain5.com/127.0.0.1
    

    【讨论】:

    • address= 不是变量。它是一个应该在所有行中重复的字符串。
    • 你是什么意思repeated?你想用address=\${line}\127.0.0.1替换像#*这样的所有行吗?
    • 如果您显示您拥有的文件并显示您想要的文件,那就太好了。
    • 我无法通过在 dnsmasq.conf 中添加脚本链接来让 dnsmasq 解析脚本。但是我创建了 dnsmasq 的 init 文件来执行脚本,并将链接添加到在 dnsmasq.conf 中作为输出获得的文件。它奏效了。
    • 评论匹配应该是[[ "$line" = "#"* ]]。系统/版本之间可能存在一些差异。
    【解决方案3】:

    注释行可以而且经常以空格开头。这是一个处理任何前面空格的 bash 原生正则表达式解决方案;

    while read line; do
      [[ "$line" =~ ^[[:space:]]*# ]] && continue
      ...work with valid line...
    done
    

    【讨论】:

      【解决方案4】:
      [ "${line:0:1}" = "#" ] && continue
      

      这需要字符串,在offset 0, length 1 处获取子字符串:

      "${line:0:1}"
      

      并检查它是否等于#

      = "#"
      

      如果是则继续循环

      && continue
      

      http://www.tldp.org/LDP/abs/html/string-manipulation.html

      【讨论】:

      • 谢谢你,我发现这很容易理解,解释得很好,而且不需要额外的复杂性(sed、awk 和以 ^ 开头的奇怪的令人毛骨悚然的语法)
      【解决方案5】:

      只有一个对我有用的是:

      while IFS=$'\n' read line
      do  
          if [[ "$line" =~ \#.* ]];then
              logDebug "comment line:$line"
          else
              logDebug "normal line:$line"
          fi
      done < myFile
      

      【讨论】:

        【解决方案6】:

        您可以使用awk进行过滤:

        awk '!/^#/{print"address=/"$0"/127.0.0.1"}' file
        

        【讨论】:

        • 你能解释一下你的答案吗?
        • 首先它说不打印以数字符号开头的行,然后在原始文本的两侧添加 $0,即要求的内容。
        【解决方案7】:

        这也可以通过 1 个sed 命令来完成:

        file="myfile"
        
        sed -i".backup" 's/^#.*$//' $file
        

        这将就地修改文件(首先创建备份副本),删除所有以# 开头的行。

        【讨论】:

          【解决方案8】:

          它有 3 个部分。请阅读每个以清楚地理解

          1. 删除#行 ----- awk -F'#' '{print $1}' t.txt
          2. 删除#创建的空行----awk 'NF &gt; 0'
          3. 以所需格式打印。 ------awk '{print "address=/"$0"/127.0.0.1"}'

          所以需要的总脚本是,

          **awk -F'#' '{print $1}' t.txt | awk 'NF > 0' | awk '{print "address=/"$0"/127.0.0.1"}'**
          

          输出:

          address=/domain1.com/127.0.0.1
          address=/domain2.com/127.0.0.1
          address=/domain3.com/127.0.0.1
          address=/domain5.com/127.0.0.1
          

          【讨论】:

            【解决方案9】:
            awk '{ if ($0 !~ /^#/){printf "address=/%s/127.0.0.1 \n",$0}}' <your_input_file>
            

            【讨论】:

              【解决方案10】:

              也许你可以试试

              [[ "$line"~="#.*" ]] && continue
              

              检查操作数中的~

              【讨论】:

              • 应该是 '=~' 而不是 '~='
              猜你喜欢
              • 1970-01-01
              • 2012-09-09
              • 2020-10-24
              • 2011-05-22
              • 1970-01-01
              • 1970-01-01
              • 2020-02-24
              • 1970-01-01
              • 2020-11-12
              相关资源
              最近更新 更多