【问题标题】:editing text files with perl使用 perl 编辑文本文件
【发布时间】:2011-01-12 10:19:54
【问题描述】:

我正在尝试编辑如下所示的文本文件:

TYPE=Ethernet
HWADDR=00:....
IPV6INIT=no
MTU=1500
IPADDR=192.168.2.247
...

(实际上是 red hat Linux 上的 /etc/sysconfig/network-scripts/ifcfg- 文件) 我想我可以使用 grep、sed、awk 或 Perl 中提供的本机文本解析功能,而不是每次要修改文件时都读取和重写文件。

例如,如果我想更改文件的 IPADDR 字段,有没有办法可以直接检索和修改该行?也许像

grep 'IPADDR=' <filename> 

但是添加一些额外的参数来修改该行?我对基于 UNIX 的文本处理语言有点陌生,所以请耐心等待...

谢谢!

【问题讨论】:

    标签: perl unix sed awk grep


    【解决方案1】:

    这将是 'ed' 命令行编辑器,类似于 sed,但会将文件放回原来的位置。

    【讨论】:

      【解决方案2】:

      因为你是redhat,你可以试试shell

      #!/bin/bash
      
      file="file"
      read -p "Enter field to change: " field
      read -p "Enter new value: " newvalue
      shopt -s nocasematch
      while IFS="=" read -r f v
      do
          case "$f" in
              $field)
                  v=$newvalue;;
          esac
          echo "$f=$v"
      done <$file > temp
      mv temp file
      

      更新:

      file="file"
      read -p "Enter field to change: " field
      read -p "Enter new value: " newvalue
      shopt -s nocasematch
      EOL=false
      IFS="="
      until $EOL
      do
          read -r f v || EOL=true
          case "$f" in
              $field)
                  v=$newvalue;;
          esac
          echo "$f=$v"
      done <$file #> temp
      #mv temp file
      

      或者,只使用 awk

      awk 'BEGIN{
          printf "Enter field to change: "
          getline field < "-"
          printf "Enter new value: "
          getline newvalue <"-"
          IGNORECASE=1
          OFS=FS="="
      }
      field == $1{
          $2=newvalue
      }
      {
          print $0 > "temp"
      }END{
          cmd="mv temp "FILENAME
          system(cmd)
      }'  file
      

      或者使用 Perl

      printf "Enter field: ";
      chomp($field=<STDIN>);
      printf "Enter new value: ";
      chomp($newvalue=<STDIN>);
      while (<>){
          my ( $f , $v ) = split /=/;
          if ( $field =~ /^$f/i){
              $v=$newvalue;
          }
          print join("=",$f,$v);
      }
      

      【讨论】:

      • 感谢您的详细回复! bash 脚本完全符合我的需要,只是它在重写文件时删除了最后一行。我只需要在 while 循环中添加一个 EOF 布尔值还是您有什么建议?
      • 这很奇怪。我对此没有意见。请尝试我编辑的“新”版本。
      【解决方案3】:

      这是一个 Perl oneliner,用于将 IPADDR 值替换为 IP 地址 127.0.01。它足够短,您应该能够看到您需要修改什么以更改其他字段*:

      perl -p -i.orig -e 's/^IPADDR=.*$/IPADDR=127.0.0.1/' filename
      

      它将“文件名”重命名为“文件名.orig”,并将文件的新版本写入“文件名”。

      Perl 命令行选项在perldoc perlrun 进行了解释(感谢提醒工具!),perl 正则表达式的语法在perldoc perlre

      *正则表达式^IPADDR=.*$,拆分成组件,意思是:

        ^         # bind to the beginning of the line
        IPADDR=   # plain text: match "IPADDR="
        .*        # followed by any number of any character (`.` means "any one character"; `*` means "any number of them")
        $         # bind to the end of the line
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多