Сравните три файла на основе столбцов с помощью Perl

Только количества UID. Если ls -l показывает файл, как принадлежится tstaerk на моем компьютере, это может быть хеш на Вашем компьютере. Затем Вам разрешают изменить (в случае rwx------). Это обычно не только в файловых системах расширения.

2
25.10.2015, 10:36
2 ответа

Перекрестный вопрос, следовательно, перекрестный ответ:

Хорошо, посмотрите на это - ваша проблема с этим разделением - потому что по умолчанию он разбивается на пробелы. Ваш второй файл имеет 3 поля по этому критерию, а не два.

Но также - вы на самом деле не ссылаетесь на одни и те же вещи, поэтому ваш цикл while (<>) { не поможет.

  • В файле 1 - вы хотите проверить значение .
  • В файле2 вы проверяете ключ (и добавляете значения).
  • В file3 у вас нет значения, только ключ.

Имея это в виду:

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

#read file1 into a hash - but invert is it's value => key instead:
#          'CKEIFJ' => 'cmr03lsp',
# etc.  
open( my $file1, '<', "file1.txt" ) or die $!;
my %file1_content = map { reverse split } <$file1>;
close($file1);

print Dumper \%file1_content;

#read file 2 - read keys, store the values. 
#split _2_ fields, so we keep both numbers as a substring:
#e.g.:
#          'cmr03lsp' => '60 70
#',

open( my $file2, '<', "file2.txt" ) or die $!;
my %file2_content = map { split( " ", $_, 2 ) } <$file2>;
close($file2);

print Dumper \%file2_content;    

#then iterate file 3, checking if:
#file1 has a matching 'key' (but inverted - as a value) 
#file2 has a cross reference. 
open( my $file3, '<', "file3.txt" ) or die $!;
while ( my $line = <$file3> ) {
    chomp $line;
    if (    $file1_content{$line}
        and $file2_content{ $file1_content{$line} } )
    {
        print
            "$file1_content{$line} $line $file2_content{$file1_content{$line}}";
    }
}
close($file3);

Это напечатает (за исключением вывода «дампер»):

fji01dde AIDJFMGKG 25 30
cmr03lsp CKEIFJ 60 70
0
27.01.2020, 22:12

-a (архив) должен делать то, что требуется.

, однако, -t (сохранение времени изменения) является конкретной командой для выполнения этой команды.

-121--195318-

Есть еще две проблемы с использованием # !/usr/bin/env

  1. Это не решает проблему указания полного пути к интерпретатору, он просто перемещает его в env .

    env не гарантировано в /usr/bin/env , чем bash гарантировано в /bin/bash или python в /usr/bin/python .

  2. env перезаписывает ARGV [0] на имя интерпретатора (e.. g bash или python).

    Это предотвращает появление имени сценария в выходных данных ps (или изменяет способ/место его отображения) и делает невозможным его поиск с помощью, например, ps -C scriptname.sh

[update 2016-06-04]

И третья проблема:

  1. Изменение PATH - это больше работа, чем просто редактирование первой строки сценария, особенно когда сценарии такие правки тривиальны. например,

    printf "% s\n" 1 i '#!' $ (тип -P python2). w | ed foo.py

    Добавление или предварительное ожидание каталога к $ PATH довольно просто (хотя вы все еще должны изменить файл, чтобы сделать его постоянным - ваш ~/.profile или что-либо еще - и это далеко не легко создать сценарий, ЧТО изменить, потому что ПУТЬ может быть установлен в любом месте сценария, а не в первой строке).

    Изменить порядок каталогов PATH значительно сложнее.... и намного сложнее, чем просто редактировать #! строка.

    И у вас все еще есть все остальные проблемы, которые дает вам использование # !/usr/bin/env .

    @ jlliagre предлагает в комментарии, что # !/usr/bin/env полезен для тестирования скрипта с несколькими версиями интерпретаторов, "только изменив их порядок PATH/PATH"

    Если это необходимо, гораздо проще просто иметь несколько #! строки в верхней части сценария (это только комментарии где угодно, кроме самой первой строки) и вырезать/копировать-и-вставить ту, которую вы хотите использовать сейчас, в первую строку.

    В vi это было бы так же просто, как перемещение курсора на #! , затем введите dd1GP или Y1GP . Даже при таком тривиальном редакторе, как nano , для копирования и вставки с помощью мыши потребуется несколько секунд.


В целом, преимущества использования # !/usr/bin/env минимальны в лучшем случае, и, конечно, даже не близки к перевесу недостатков. Даже "удобное" преимущество во многом иллюзорно.

IMO, это глупая идея, продвигаемая определенным видом программистов, которые думают, что операционные системы не являются чем-то, с чем нужно работать, они являются проблемой , которую нужно работать (или игнорировать в лучшем случае).

PS: вот простой сценарий для изменения интерпретатора нескольких файлов одновременно.

хижина изменения.sh :

#!/bin/bash

interpreter="$1"
shift

if [ -z "$(type -P $interpreter)" ] ; then
  echo "Error: '$interpreter' is not executable." >&2
  exit 1
fi

if [ ! -d "$interpreter" ] && [ -x "$interpreter" ] ; then
  shebang='#!'"$(realpath -e $interpreter)" || exit 1
else
  shebang='#!'"$(type -P $interpreter)"
fi

for f in "$@" ; do
  printf "%s\n" 1 i "$shebang" . w | ed "$f"
done

Запустите его, например, как change-shebang.sh python2.7 * .py или change-shebang.sh $ HOME/bin/my-experimental-ruby * .rb

-121--1207-

Основная проблема сценария заключалась в том, что к моменту окончания цикла while (< >) @ ARGv Вы должны получить счет arg перед петлей. И помните, что массивы perl основаны на нуле, поэтому вы должны вычесть 1 из счета.

Вот фиксированная версия, которая выдает запрошенный результат.

$ cat compare.pl 
#!/usr/bin/perl
use strict;
use warnings;

my $numargs=@ARGV-1;
my %data=();

while (<>) {  
    my ( $key, $value ) = split;  
    push( @{ $data{$key} }, $value );  

}  

foreach my $key ( sort keys %data ) {  
    if ( @{ $data{$key} } >= $numargs ) {  
    print join( "\t", $key, @{ $data{$key} } ), "\n";  
    }  
}

$ ./compare.pl file1 file2 file3
cmr03lsp    CKEIFJ  60
dlp02sle    VMCFIJGM    40
fji01dde    AIDJFMGKG   25
2
27.01.2020, 22:12

Теги

Похожие вопросы