【问题标题】:awk file manipulationawk 文件操作
【发布时间】:2011-03-10 18:08:00
【问题描述】:

我的文本文件中有以下文字,我想提取如下。

device1 te rfe3 -1     10.1.2.3   device1 te rfe3
device2 cdr thr        10.2.5.3   device2 cdr thr
device4                10.6.0.8   device4
device3 hrdnsrc dhe    10.8.3.6   device3 hrdnsrc dhe

我的目标是提取设备名称和 IP 地址以剥离其他所有内容。 设备名称后没有图案,其中一些有 2-3 个单词,其中一些没有任何东西。我也不需要第三列。我正在看这样的结果。

device1   10.1.2.3
device2   10.2.5.3 
device3   10.8.3.6 
device3   10.8.9.4 

这可能吗?提前致谢。

【问题讨论】:

    标签: perl shell unix awk sed


    【解决方案1】:
     sed -r 's/^([^ ]*) .* (([0-9]{1,3}\.){3}[0-9]{1,3}).*$/\1 \2/'
    

    概念证明

    $ sed -r 's/^([^ ]*) .* (([0-9]{1,3}\.){3}[0-9]{1,3}).*$/\1 \2/' ./infile
    device1 10.1.2.3
    
    device2 10.2.5.3
    
    device4 10.6.0.8
    
    device3 10.8.3.6
    

    【讨论】:

      【解决方案2】:

      awk 中,类似于

      $ awk '{
               for (f = 2; f <= NF; f++) {
                 if ($f ~ /^([0-9]+\.){3}[0-9]+$/) {
                   print $1, $f
                   break
                 }
               }
             }' file
      

      这是一个成绩单:

      mress:10192 Z$ cat pffft.awk
      {
        for (f = 2; f <= NF; f++) {
          if ($f ~ /^([0-9]+\.){3}[0-9]+$/) {
            print $1, $f
            break
          }
        }
      }
      mress:10193 Z$ cat pfft.in 
      device1 te rfe3 -1     10.1.2.3   device1 te rfe3
      device2 cdr thr        10.2.5.3   device2 cdr thr
      device4                10.6.0.8   device4
      device3 hrdnsrc dhe    10.8.3.6   device3 hrdnsrc dhe
      mress:10194 Z$ awk -f pffft.awk pfft.in
      device1 10.1.2.3
      device2 10.2.5.3
      device4 10.6.0.8
      device3 10.8.3.6
      mress:10195 Z$ _
      

      【讨论】:

      • 我无法理解该回复。
      • @dan:awk 不会更改文件。它从文件中读取文本并将其写入标准输出。要更新文件,请使用 awk '...' file &gt; file2 之类的内容重定向输出。 不要使用相同的文件进行输入和输出,因为操作系统会在打开文件进行写入时立即截断文件。
      • 我确实复制并粘贴了除 (>) 之外的每个命令,最后我做了 myFile > myFile2,输出文件的结果为 0。我错过了什么吗?我以前从未使用过多行 awk 命令,可能是我错过了一些东西。谢谢楼主!!!
      • 你可能错过了一些东西。我会编辑一些更有用的东西;出于某种原因,我在我的示例上完全隔开,不能剪切和粘贴。
      • 我觉得你那里多了一个+[0-9]++$应该是[0-9]+$吧?
      【解决方案3】:

      在 perl 中

      perl -ne 'next if /^\s*$/ ; /^(\w+).*?(\d+(\.\d+){3})/; print "$1\t$2\n"' test_file
      

      对于排序的结果,您可能可以通过管道将输出传递给排序命令

      perl -ne 'next if /^\s*$/ ; /^(\w+).*?(\d+(\.\d+){3})/; print "$1\t$2\n"' test_file | sort
      

      更新脚本如版本

      my $test_file = shift or die "no input file provided\n";
      
      # open a filehandle to your test file
      open my $fh, '<', $test_file or die "could not open $test_file: $!\n";
      
      while (<$fh>) {
          # ignore the blank lines
          next if /^\s*$/;
      
          # regex matching
          /               # regex starts
          ^               # beginning of the string
          (\w+)           # store the first word in $1
          \s+             # followed by a space
          .*?             # match anything but don't be greedy until...
          (\d+(\.\d+){3}) # expands to (\d+\.\d+\.\d+\.\d+) and stored in $2
          /x;             # regex ends 
      
          # print first and second match
          print "$1\t$2\n"
      }
      

      【讨论】:

      • 太棒了!这在命令行上完美运行,所以我想包含在我的 perl 脚本中。这在脚本中是如何工作的。任何想法!!!非常感谢你
      【解决方案4】:

      Python 不在您的列表中,但类似的方法可能有用。

      import sys
      import re
      pattern= re.compile( "^(\w+)\s.*?\s(\d+\.\d+\.\d+\.\d+)\s.*$" )
      for line in sys.stdin:
          match= pattern.match( line )
          sys.stdout.write( "{0} {1}".format( match.group(1), match.group(2) ) )
      

      它应该可以在大多数 Linux 平台上运行,因为已经安装了 Python。

      【讨论】:

      • 不知道它是如何工作的。在linux命令行上添加你的命令?或创建为脚本并运行。你能告诉我怎么?再次感谢!
      • 模式应该是 "^(\w+)\s.*?\s(\d+\.\d+\.\d+\.\d+)\s" 和要打印的组 "匹配组(1),匹配组(2)”。
      【解决方案5】:

      假设输入文件的字段总是与相同的列对齐,最短的 POSIX 解决方案是

      $ cut -c1-8,23-33 x
      device1  10.1.2.3
      
      device2  10.2.5.3
      
      device4  10.6.0.8
      
      device3  10.8.3.6
      

      【讨论】:

        【解决方案6】:

        根据 cruft 获得的 IP 号码有多接近,这可能会或可能不会满足您的需求:

        sed -re 's/^([^ ]*).* ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1 \2/g'
        

        【讨论】:

        • 命令没有任何反应。不过感谢您的回复。
        【解决方案7】:

        À la cut 使用 perl 的解决方案,如果文件始终采用相同的格式列,您可以使用“解包”:

        perl -nE 'say unpack("A8 x14 A9")' data.txt
        

        或者使用正则表达式获取第一个单词后跟空格^(\w+\s),然后是. 后面的一个或多个数字3 次(\d+(\.\d+){3})

        perl -nE '/^(?<name>\w+\s).*?(?<ip>\d+(\.\d+){3})/; 
                 say "$+{name} $+{ip}" '  data.txt
        

        命名捕获 ($+{name} $+{ip}) 只是为了好玩:-)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-19
          • 2017-04-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-18
          相关资源
          最近更新 更多