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

发布于 2024-12-09 15:27:48 字数 886 浏览 1 评论 0原文

所以,如果标题没有意义,这就是我想做的:

我有 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

如你所见,它是 ip 地址,用“:”分隔

File2 基本上是一个 apache 虚拟主机条目,或 httpd .conf 文件。这并不重要。只需知道 file2 包含 file1 第一列中某处的 IP 地址即可。并且需要将它们替换为 file1 的第二列。

出于某种原因,这个简单的问题让我感到困惑。我尝试过一些非常粗糙的事情,但总是陷入困境。

我知道我可以使用 awk 将它们分开,并且我知道我可以将其通过管道传输到 sed 中以对 file2 进行操作。

但我似乎无法理解将第 1 列“映射”到第 2 列的最佳方法,以便这实际上可以发生。

我愿意使用 perl、ruby、python,或者实际上任何实现此目的的方法,并且我非常希望简要说明如何解决此问题。

请要求任何澄清,我很乐意提供。

非常感谢!

So, if the title didn't make sense, here's what I'm trying to do:

I have 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 ":"

File2 is basically an apache virtual host entry, or httpd.conf file. It doesn't really matter. Just know that file2 contains the ip addresses from the first column of file1 somewhere in there. And they need to be replaced by the second column of 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.

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.

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.

Please ask for any clarification, and I'll be glad to supply it.

Thanks so much in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

甜柠檬 2024-12-16 15:27:48

将 file1 中的 IP 对读取到哈希中,例如 $ip{$old} = $new。我假设没有重复的IP。通过 file2 查找 IP,并使用正则表达式,例如:

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

编写类似以下内容的代码:

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;
}

根据需要重定向到输出文件。 IP 可能需要更好的正则表达式。

Read the IP pairs from file1 into a hash, e.g. $ip{$old} = $new. I assume there are no duplicate IPs. Go through file2 looking for IPs, and use a regex such as:

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.

木槿暧夏七纪年 2024-12-16 15:27:48
perl  -ne '/(.*):(.*)/; (exists $ips{$1}) ? (print "$ips{$1}\n") : ($ips{$1} = $2);' f1 f2

这会循环遍历文件 f1,然后循环遍历文件 f2。它将它们按照“:”字符分开,如果我们之前没有见过前半部分,请将其粘贴到散列中。如果我们之前看过前半部分,请打印我们存储在哈希中的值。

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

This loops over file f1 then file 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.

素罗衫 2024-12-16 15:27:48
sed -e "s:$(sed -e ':a;$!N;s/\n/:g;s:/g;ta' file1):" file2

内部 sed 为外部 sed 创建一个多表达式正则表达式以应用于 file2..
要安全地就地更新原始文件,您可以通过 sponge 将输出传输到 ir(来自包 moreutils)。

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..
To securely update your original file insitu, you can pipe the output to ir via sponge (from package moreutils).

殊姿 2024-12-16 15:27:48
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
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
沩ん囻菔务 2024-12-16 15:27:48

我使用perl。我们将其命名为mapper.pl。将映射文件作为参数,然后将 stdin 映射到 stdout。所以你像这样使用它

perl mapper.pl file1 < file2 > file2.new

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/\\
amp;/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

Id use perl. Lets call it mapper.pl. Takes map file as an arg, and then maps stdin to stdout. So you use it like this

perl mapper.pl file1 < file2 > file2.new

The mapper.pl program is something like:

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/\\
amp;/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
感性 2024-12-16 15:27:48

感谢所有精彩的答案!

我受到他们的启发,创建了一个 ruby​​ 版本:(它可以使用一些工作/减少,它还不是很 ruby​​esque,但它可以工作)

#!/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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文