简体   繁体   English

需要用file1的第二列替换与file1的第一列匹配的file2中的字符串

[英]Need to replace string in file2 that matches first column of file1 with second column of file1

So, if the title didn't make sense, here's what I'm trying to do: 因此,如果标题没有意义,这就是我想要做的:

I have file1: 我有file1:

66.115.135.84:123.123.123.1
66.115.135.85:123.123.123.2
66.115.135.86:123.123.123.3
66.115.135.87:123.123.123.4
66.115.135.88:123.123.123.5
66.115.135.89:123.123.123.6
66.115.135.90:123.123.123.7
66.115.135.91:123.123.123.8
66.115.135.92:123.123.123.9
66.115.135.93:123.123.123.10
66.115.135.94:123.123.123.11
66.115.135.95:123.123.123.12
66.115.135.96:123.123.123.13
66.115.135.97:123.123.123.14

As you can see, it's ip addresses, separated by a ":" 如您所见,它是IP地址,以“:”分隔

File2 is basically an apache virtual host entry, or httpd.conf file. File2本质上是一个Apache虚拟主机条目或httpd.conf文件。 It doesn't really matter. 没关系。 Just know that file2 contains the ip addresses from the first column of file1 somewhere in there. 只是知道file2包含来自file1第一列的IP地址。 And they need to be replaced by the second column of file1. 并且它们需要替换为file1的第二列。

For some reason, this simple problem has left me bewildered. 由于某种原因,这个简单的问题使我感到困惑。 I've tried some pretty gnarly things, but keep getting stuck. 我已经尝试了一些非常粗糙的东西,但是一直卡住了。

I know I can separate them using awk, and i know i could pipe that into sed to act on file2. 我知道我可以使用awk分隔它们,并且我知道可以将其传送到sed中以对file2起作用。

But I can't seem to wrap my head around the best way to "map" column 1 to column 2 so that this can actually happen. 但是我似乎无法将最好的方法“将”第1列“映射”到第2列,以至于这种情况确实发生。

I'm willing to use perl, or ruby, or python, or really any method of achieving this, and I would very much like a brief explanation of how you are able to solve this. 我愿意使用perl或ruby或python或任何实现此目的的方法,并且我非常希望对如何解决此问题进行简要说明。

Please ask for any clarification, and I'll be glad to supply it. 请要求任何澄清,我们很乐意提供。

Thanks so much in advance! 非常感谢!

Read the IP pairs from file1 into a hash, eg $ip{$old} = $new . 将IP1对从file1读入哈希,例如$ip{$old} = $new I assume there are no duplicate IPs. 我假设没有重复的IP。 Go through file2 looking for IPs, and use a regex such as: 遍历file2寻找IP,并使用正则表达式,例如:

s#($IPregex)# $ip{$1} // $1 #eg;

Code something like: 代码类似:

use autodie;

open my $fh, '<', "file1";
my %ip;
while (<$fh>) {
    chomp;
    my ($key, $val) = split /:/, $_, 2;
    $ip{$key} = $val;
}

open $fh, '<', "file2";
my $rx = qr/\b\d{0,3}\.\d{0,3}\.\d{0,3}\.\d{0,3}\b/;

while (<$fh>) {
    s#($rx)# $ip{$1} // $1 #eg;
    print;
}

Redirect to output file as needed. 根据需要重定向到输出文件。 Might need a better regex for the IP. 可能需要更好的IP正则表达式。

perl  -ne '/(.*):(.*)/; (exists $ips{$1}) ? (print "$ips{$1}\n") : ($ips{$1} = $2);' f1 f2

This loops over file f1 then file f2. 这将依次遍历文件f1和文件f2。 It splits them on the ':' character and if we haven't seen the first half before, stick it in the hash. 它将它们分割为':'字符,如果之前没有看到前一半,则将其粘贴在哈希中。 If we have seen the first half before, print the value we stored in the hash. 如果我们已经看过前半部分,请打印存储在哈希中的值。

sed -e "s:$(sed -e ':a;$!N;s/\n/:g;s:/g;ta' file1):" file2

The inner sed creates a multi-expression regex for the outer sed to apply to file2.. 内部sed为外部sed创建一个多表达式正则表达式,以应用于file2。
To securely update your original file insitu, you can pipe the output to ir via sponge (from package moreutils ). 为了安全地就地更新原始文件,您可以通过sponge将输出通过管道传输到ir(来自moreutils包)。

awk '
  FILENAME == ARGV[1] {
    split($0, ary, /:/)
    map[ary[0]] = ary[1]
    next
  }
  {
    for (i=1; i<=NF; i++) {
      if ($i in map)
        $i = map[$i]
    }
    print
  }
' file1 file2 > file2.new

Id use perl. id使用perl。 Lets call it mapper.pl . 让我们称之为mapper.pl Takes map file as an arg, and then maps stdin to stdout . 将映射文件作为arg,然后将stdin映射到stdout So you use it like this 所以你这样用

perl mapper.pl file1 < file2 > file2.new

The mapper.pl program is something like: mapper.pl程序类似于:

use strict;
use warnings;

# Prototypes
sub readMap($);

# Main program
{
    if( scalar(@ARGV) != 1 )
    {
        die "usage: mapper.pl mapfile";
    }
    my %map = readMap( $ARGV[0] );
    while( my $line = <STDIN> )
    {
        foreach my $old ( keys(%map) )
        {
            my $old_re = $old;
            # Escape metacharacters
            $old_re =~ s/\W/\\$&/g;
            $line =~ s/$old_re/$map{$old}/g;
        }
        print $line;
    }
} # END main

sub readMap($)
{
    my $mapname = $_[0];
    my %map;
    open( MAPFILE, "<$mapname" ) || die "open($mapname): $!";
    while( my $line = <MAPFILE> )
    {
        if( $line =~ /^\s*([^:]+):(.*?)\s*$/ )
        {
            $map{$1} = $2;
        }
        else
        {
            warn "Invalid line: $line";
        }
    }
    close( MAPFILE );
    return( %map );
} # END readMap

Thanks for all of the great answers! 感谢您提供的所有出色答案!

I was inspired by them to create a ruby version: (it could use some work/reduction, it's not very rubyesque yet, but it works) 我受到他们的启发,创建了一个红宝石版本:(它可以进行一些工作/还原,虽然还不是很红宝石,但是可以用)

#!/usr/bin/ruby
#replaces old ips for new ips in virt file
@orig_ips=Array.new
@new_ips=Array.new
File.open("/home/kevin/scripts/ruby_scripts/test.virt", "r").each do |line|
  if line =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
    @orig_ips.push(line.split.last.chop)
  end
end

File.open("/home/kevin/scripts/ruby_scripts/new_ip_list", "r").each do |line|
  @new_ips.push(line.split.last)
end

f = File.open("/home/kevin/scripts/ruby_scripts/test.virt")
working_file = f.read
for count in 0..@orig_ips.count - 1  do
  old = @orig_ips[count]
  new = @new_ips[count]
  working_file.gsub!(old, new)
end
puts working_file

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果file1的第一列与file2中的任何字符串匹配,则将其替换为file1的第二列 - If the first column of file1 matches any string in file2, then replace it with the second column of file1 如何循环匹配文件 1 的第 1 列和第 2 列与文件 2 的第 1 列中的单元格,以便将它们替换为文件 2 的第 2 列中的相邻单元格? - How do you loop and match column 1 and 2 of file1 with cell in column1 of file2 in order to replace them with the adjacent cell in column 2 of file 2? Perl 在屏幕或 File3 中从 file1 和 file2 打印匹配和不匹配的字符串 - Perl Print matched and unmatched String from file1 and file2 in screen or File3 Perl 使用 file2 从 file1 中删除单词 - Perl removing words from file1 with file2 匹配文件1和文件2中的数据范围 - match data range from file1 with file2 tail -f file1 | perl -pe&#39;$ _&#39;&gt; file2不向file2输出任何内容 - tail -f file1 | perl -pe '$_' > file2 does not output anything to file2 在Perl中获取file2中没有出现的所有行的最快方法是什么? - What's the fastest way in Perl to get all lines of file1 that do not appear in file2? Perl 打印匹配且无匹配字符串来自 file1 匹配 file2 匹配百万记录 - Perl print match and no match strings from file1 match in file2 match with million records 无法打开本地文件/ dir1 / file1:无此文件或目录:PERL代码 - Cannot open Local file /dir1/file1 : No such file or directory: PERL code 第一列匹配; 读取模式并替换为第二个文件列中的特定值 - First columns match; read pattern and replace with specific values in the second file column
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM