Присоединение к двум файлам с уникальным идентификатором

Железный Shell Панелей мог бы быть, что Вы ищете.

Железная Оболочка Панелей или короткий ibsh является моей первой попыткой создать ограниченную рабочую среду для Linux/Unix. Я уверен, что многие системные администраторы желают или пожелали способа заблокировать некоторых/всех пользователей в безопасную темницу, где они могут только причинить вред своим собственным файлам.

Вот еще некоторая информация о том, как использовать ее.

9
12.09.2013, 01:46
5 ответов
awk 'BEGIN { while(getline < "file2" ) { codes[$1] = $2 } }
     { printf "%4s%s\n", codes[$1], substr($0, 5) }' file1
8
27.01.2020, 20:04
  • 1
    Изящное решение, которое я только с некоторыми основными умениями и навыками действительно понимаю. Спасибо! –  Staffan Scherloff 11.09.2013, 14:23
  • 2
    Программа читает один файл в память, прежде чем это начнет работать. Если файлы становятся больше, который может значительно уменьшить производительность. Для большего файла не может использоваться этот метод. –  miracle173 12.09.2013, 00:19

Несколько нас хотели видеть, могли ли мы решить это использование задач join только. Это - моя попытка сделать это. Так как это частично работает, @Terdon должен мне ужин 8-).

Команда

$ join -a1 -1 1 -2 1 -o 2.2 1.1 1.2 1.3 1.4 1.5 1.6 1.7 -e "N/A" \
     <(sort file1) <(sort file2)

Пример

$ join -a1 -1 1 -2 1 -o 2.2 1.1 1.2 1.3 1.4 1.5 1.6 1.7 -e "N/A" <(sort file1) <(sort file2) | column -t
N/A   060090  AKRABERG          FYR         DN    6138  -666  101
EKVG  060100  VAGA              FLOGHAVN    DN    6205  -728  88
N/A   060110  TORSHAVN          DN          6201  -675  55    N/A
N/A   060120  KIRKJA            DN          6231  -631  55    N/A
N/A   060130  KLAKSVIK          HELIPORT    DN    6221  -656  75
N/A   060160  HORNS             REV         A     DN    5550  786
N/A   060170  HORNS             REV         B     DN    5558  761
N/A   060190  SILSTRUP          DN          5691  863   0     N/A
N/A   060210  HANSTHOLM         DN          5711  858   0     N/A
EKGF  060220  TYRA              OEST        DN    5571  480   43
EKTS  060240  THISTED           LUFTHAVN    DN    5706  870   8
N/A   060290  GROENLANDSHAVNEN  DN          5703  1005  0     N/A
EKYT  060300  FLYVESTATION      AALBORG     DN    5708  985   13
N/A   060310  TYLSTRUP          DN          5718  995   0     N/A
N/A   060320  STENHOEJ          DN          5736  1033  56    N/A
N/A   060330  HIRTSHALS         DN          5758  995   0     N/A
EKSN  060340  SINDAL            FLYVEPLADS  DN    5750  1021  28

Подробнее

Вышеупомянутое использует в значительной степени каждую опцию, доступную join который говорит моему пищеварительному тракту, что мы используем его неправильно, как в некотором типе Frankenstein путь, но мы все учимся здесь, таким образом, это в порядке... Я предполагаю.

Переключатель -a1 говорит соединению включать любые строки, которые не делают имеет соответствующее соответствие от file2 в file1. Таким образом, это - то, что управляет этими строками, которые будут отображены:

N/A   060330  HIRTSHALS         DN          5758  995   0     N/A

-1 1 и -2 1 говорят который столбцы присоединиться к строкам из этих 2 файлов на, главным образом их 1-е столбцы. -o ... говорит который столбцы из этих 2 файлов отобразиться и в который порядок.

-e "N/A" говорит для использования строки "N/A" в качестве значения заполнителя для печати для полей, которые считают пустыми join.

Последние 2 аргумента подают эти 2 файла, file1 & file2 как отсортировано в команду соединения.

Будьте добры, так как это - происходящая работа, и мы пытаемся продемонстрировать, как можно было бы решить этот тип проблемы с помощью join команда, так как это, казалось бы, было бы типом проблемы, для которой это было предназначено.

Нерешенные вопросы

  1. 3-й столбец

    Главный - то, как бороться с 3-м столбцом, так как это - соединение 1 слова и 2 значений слова. Это походит на главный камень преткновения для join и я не могу выяснить путь вокруг этого. Любое руководство ценилось бы.

  2. Интервал

    Весь исходный интервал потерян с join и я не вижу способ сохранить его вокруг также. Так join не мог бы быть правильный способ иметь дело с этими типами проблем, в конце концов.

  3. Кажется, работает хотя?

    После большого изгиба с командной строкой общее решение там, таким образом, это действительно кажется, что может работать по крайней мере частично, таким образом, это могло использоваться в ядре решения и затем использовать другие инструменты такой как awk и sed очищать его. Это вызывает вопрос хотя: "Если Вы очищаете его с awk & sed какой-либо путь, затем Вы могли бы также просто использовать их непосредственно?".

7
27.01.2020, 20:04
  • 1
    @Terdon - видят этот ответ, сообщают мне то, что Вы думаете. –  slm♦ 12.09.2013, 00:04
  • 2
    +1 я думаю, что это - инструмент Unix, который был запрограммирован для решения такой задачи –  miracle173 12.09.2013, 00:22
  • 3
    , почему не-e "" вместо-e "N/A". разве это не работает (я не могу попробовать его)? –  miracle173 12.09.2013, 00:26
  • 4
    @miracle173 - любой ценой да использование пространства, поскольку аргумент действительно работает также. Я выбрал N/A так, чтобы было очевидно, что это делало. –  slm♦ 12.09.2013, 00:32
  • 5
    @terdon - да это была забавная проблема тем не менее, обладаемый работать над ним вместе, надо надеяться, мы можем работать над некоторыми будущими проблемами вместе также. Я все еще думаю, что этот ответ будет служить полезной цели на сайте, так как я не мог найти много экстремальных примеров join таким образом, теперь Интернет имеет этого. 8-) –  slm♦ 12.09.2013, 05:29

Это должно быть возможным использованием join но я не могу выяснить, как заставить его распечатать пробелы и пустые поля правильно. Так или иначе этот небольшой сценарий Perl добьется цели:

#!/usr/bin/env perl

## Open file2, the one that contains the codes
## it is expected to be the 1st argument given to the script.
open($a,"$ARGV[0]"); 

## Read the number<=>code pairs into a hash (an associative array)
## called 'k'
while (<$a>) {
    chomp; @f=split(/\s+/); $k{$f[0]}=$f[1];
}

## Open file1, the one that contains the data
## it is expected to be the 2nd argument given to the script.
open($b,"$ARGV[1]"); 
## Go through the file
while (<$b>) {
    ## Split each line at white space into the array @f
    @f=split(/\s+/);  

    ## $f[1] is the 6 digit number that defines the different stations.
    ## If this number has an entry in the hash %k, if it was found
    ## in file2, replace the first 4 spaces with its value from the hash.
    s/^\s{4}/$k{$f[1]}/ if defined($k{$f[1]});

    ## Print each line of the file
    print; 
}

Сохраните это как foo.pl и выполненный следующим образом:

$ perl foo.pl file2 file1
         060090 AKRABERG FYR                        DN  6138   -666     101
EKVG     060100 VAGA FLOGHAVN                       DN  6205   -728      88
         060110 TORSHAVN                            DN  6201   -675      55
         060120 KIRKJA                              DN  6231   -631      55
         060130 KLAKSVIK HELIPORT                   DN  6221   -656      75
         060160 HORNS REV A                         DN  5550    786      21
         060170 HORNS REV B                         DN  5558    761      10
         060190 SILSTRUP                            DN  5691    863       0
         060210 HANSTHOLM                           DN  5711    858       0
EKGF     060220 TYRA OEST                           DN  5571    480      43
EKTS     060240 THISTED LUFTHAVN                    DN  5706    870       8
         060290 GROENLANDSHAVNEN                    DN  5703   1005       0
EKYT     060300 FLYVESTATION AALBORG                DN  5708    985      13
         060310 TYLSTRUP                            DN  5718    995       0
         060320 STENHOEJ                            DN  5736   1033      56
         060330 HIRTSHALS                           DN  5758    995       0
EKSN     060340 SINDAL FLYVEPLADS                   DN  5750   1021      28
4
27.01.2020, 20:04
  • 1
    Это работает превосходное. Большое спасибо - я действительно ценю Ваше объяснение текста в коде. –  Staffan Scherloff 11.09.2013, 14:22
  • 2
    @StaffanScherloff пожалуйста. Если это отвечает на Ваш вопрос, отметьте его, как принято, таким образом, вопрос может быть отмечен, как отвечено. –  terdon♦ 11.09.2013, 14:26
  • 3
    @StaffanScherloff вообще-то, если задуматься, примите awk один, это намного лучше. – terdon 5 минут назад –  terdon♦ 11.09.2013, 14:40
  • 4
    @terdon - Вы носились с этим еще использующим соединение? Походивший способ пойти, никогда не использовал -o функция прежде, не работая как я ожидал бы. –  slm♦ 11.09.2013, 16:47
  • 5
    @slm не, я думал о некоторой комбинации -o и -e но не мог заставить это печатать строки, которые не имели никакой записи в file2. Удача, мне было бы интересно знать, возможно ли это. –  terdon♦ 11.09.2013, 16:51

Bash сделает.

#!/usr/bin/env bash

# ### create a psuedo hash of icao locator id's
# read each line into an array
while read -a line; do
  # set icao_nnnnnn variable to the value
  declare "icao_${line[0]}"=${line[1]}
done <file2


# ### match up icao id's from file1
# read in file line at a time
while IFS=$'\n' read line; do
  # split the line into array
  read -a arr <<< "$line"
  # if the icao_nnnnnn variable exists, it will print out
  var="icao_${arr[0]}"
  printf "%-8s %s\n" "${!var}" "$line"
done <file1

Посмотрите, что это ТАК отвечает за детали того, что продолжает ассоциативный массив поддержек Bash 4 "хеша" исходно, но это должно работать в 3+4 (возможно, 2?)

Вам, возможно, понадобилась бы к левой обрезке строка от file1 для получения форматирования.

3
27.01.2020, 20:04

Вот простой способ сделать это с помощью join (+ еще пару инструментов) и сохранить интервал. Оба файла, кажется, отсортированы по номеру станции, так что никакой дополнительной сортировки не требуется:

join -j1 -a1 -o 2.2 -e "    " file1 file2 | paste -d' ' - <(cut -c6- file1)

Часть перед трубой очень похожа на slm, используемый в его ответе, так что я не буду повторять это снова. Единственное отличие в том, что я использую -e " - строку с четырьмя пробелами как замену отсутствующим полям ввода и -o 2.2 для вывода только 2-го поля файла2
. Итак, присоединяйтесь к -j1 -a1 -o 2. 2 -e " " " file1 file2 выдает колонку шириной в четыре карата (внизу она не видна, но после EK** ничего нет, а пустые строки на самом деле четыре пробела):


EKVG







EKGF
EKTS

EKYT



EKSN

затем вставляем этот (используя пробел в качестве разделителя) в file1, из которого вырезаем первые 5 символов | вставляем -d' ' - <(вырезаем -c6- file1)
Конечный результат:

         060090 AKRABERG FYR                        DN  6138   -666     101
EKVG     060100 VAGA FLOGHAVN                       DN  6205   -728      88
         060110 TORSHAVN                            DN  6201   -675      55
         060120 KIRKJA                              DN  6231   -631      55
         060130 KLAKSVIK HELIPORT                   DN  6221   -656      75
         060160 HORNS REV A                         DN  5550    786      21
         060170 HORNS REV B                         DN  5558    761      10
         060190 SILSTRUP                            DN  5691    863       0
         060210 HANSTHOLM                           DN  5711    858       0
EKGF     060220 TYRA OEST                           DN  5571    480      43
EKTS     060240 THISTED LUFTHAVN                    DN  5706    870       8
         060290 GROENLANDSHAVNEN                    DN  5703   1005       0
EKYT     060300 FLYVESTATION AALBORG                DN  5708    985      13
         060310 TYLSTRUP                            DN  5718    995       0
         060320 STENHOEJ                            DN  5736   1033      56
         060330 HIRTSHALS                           DN  5758    995       0
EKSN     060340 SINDAL FLYVEPLADS                   DN  5750   1021      28
2
27.01.2020, 20:04

Теги

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