Присоединитесь к двум файлам, соответствуя на столбце, с повторениями

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

mpc | head -n 1 | sed  's/^/"/g ; s/$/"/g' | xargs rm --

sed добавляет кавычки вокруг Вашего имени файла, и xargs поворачивает вход, который это получает к аргументам в пользу команды, которую это выполняет (в этом случае, команда комнаты).

7
26.01.2014, 01:18
5 ответов

Простое решение с awk:

awk -v FILE_A="file-A" -v OFS="\t" 'BEGIN { while ( ( getline < FILE_A ) > 0 ) { VAL = $0 ; sub( /^[^ ]+ /, "", VAL ) ; DICT[ $1 ] = VAL } } { print $0, DICT[ $3 ] }' file-B

Вот прокомментированная версия:

awk -v FILE_A="file-A" -v OFS="\t" '
BEGIN {

  # Loop on the content of file-A
  # to put the values in a table

  while ( ( getline < FILE_A ) > 0 ){

     # Remove the index from the value
     VAL = $0
     sub( /^[^ ]+ /, "", VAL )

     # Fill the table
     DICT[ $1 ] = VAL
  }
}
{

  # Print the line followed by the
  # corresponding value
  print $0, DICT[ $3 ]

}' file-B
5
27.01.2020, 20:16
  • 1
    Jean, Благодарит Вас за Ваш ответ.:) Я получил лучший результат Вашей справки. –  JOSS 25.01.2014, 15:31
  • 2
    @JOSS, Если Вы принимаете awk ответ, необходимо удалить тег script удара. –  Ricky Beam 25.01.2014, 23:29
$ cat b | while read b; do key=$(echo $b | awk '{print $3}'); /bin/echo -n "$b  "; grep -w $key a | cut -d\  -f2-; done
01-Dec-2013 01.664  001     AAA CAC 1083  Apple, CA
01-Dec-2013 01.664  020     AAA CAC 0513  Banana, CN
01-Dec-2013 01.668  023     AAA CAC 1091  Apple, LA
01-Dec-2013 01.668  101     AAA CAC 0183  Orange, OS
01-Dec-2013 01.674  200     AAA CAC 0918  Kiwi, AA
01-Dec-2013 01.674  045     AAA CAC 0918  Orange, TT
01-Dec-2013 01.664  001     AAA CAC 2573  Apple, CA
01-Dec-2013 01.668  101     AAA CAC 1091  Orange, OS
01-Dec-2013 01.668  020     AAA CAC 6571  Banana, CN
01-Dec-2013 01.668  023     AAA CAC 2148  Apple, LA
01-Dec-2013 01.674  200     AAA CAC 0918  Kiwi, AA
01-Dec-2013 01.668  045     AAA CAC 5135  Orange, TT

Я подозреваю awk конструкция может быть сделана более изящным способом, но это, кажется, работает.

2
27.01.2020, 20:16
  • 1
    благодарит, это работает. но действительно ли возможно использовать массив? –  JOSS 25.01.2014, 09:08

join утилита выполняет "соединение равенства" на указанных файлах и пишет результат в стандартный вывод. "Объединяющее поле" является полем в каждом файле, которым сравнены файлы.

Другими словами, у Вас есть два файла, которые совместно используют столбец. Можно присоединиться к строкам тех файлов, где столбец равен.

Поэтому давайте попробуем:

$ join -1 1 -2 3 a b
001 Apple, CA 01-Dec-2013 01.664 AAA CAC 1083
020 Banana, CN 01-Dec-2013 01.664 AAA CAC 0513
023 Apple, LA 01-Dec-2013 01.668 AAA CAC 1091
101 Orange, OS 01-Dec-2013 01.668 AAA CAC 0183
200 Kiwi, AA 01-Dec-2013 01.674 AAA CAC 0918

Да, работы. Но не в формате Вы указали. Поэтому давайте подкачаем файлы:

$ join -1 3 -2 1 b a
001 01-Dec-2013 01.664 AAA CAC 1083 Apple, CA
020 01-Dec-2013 01.664 AAA CAC 0513 Banana, CN
023 01-Dec-2013 01.668 AAA CAC 1091 Apple, LA
101 01-Dec-2013 01.668 AAA CAC 0183 Orange, OS
200 01-Dec-2013 01.674 AAA CAC 0918 Kiwi, AA

Намного лучше. Все еще совершенно верно, так как объединяемое поле обнаруживается сначала. Awk может согласовать это:

$ join -1 3 -2 1 b a | awk '{print $2,$3,$1,$4,$5,$6,$7,$8}'
01-Dec-2013 01.664 001 AAA CAC 1083 Apple, CA
01-Dec-2013 01.664 020 AAA CAC 0513 Banana, CN
01-Dec-2013 01.668 023 AAA CAC 1091 Apple, LA
01-Dec-2013 01.668 101 AAA CAC 0183 Orange, OS
01-Dec-2013 01.674 200 AAA CAC 0918 Kiwi, AA

Таким образом, там Вы идете. Поля находятся в том же порядке. В awk можно использовать printf или вставьте некоторые вкладки, если Вы хотите получить точный интервал, но я думаю, что Вы получите идею.

2
27.01.2020, 20:16
  • 1
    Обратите внимание, что необходимо отсортировать входные файлы на объединяющем поле для join работать правильно. –  Stéphane Chazelas 25.01.2014, 10:49
  • 2
    join не совершенно правильно для вопроса, также. Существует больше строк B, чем A; соединение не произведет все строки. И это уничтожает фиксированную ширину поля (т.е. ест пробелы), –  Ricky Beam 25.01.2014, 11:20
  • 3
    @RickyBeam - Неправильно. join определенно правильный инструмент для этого задания: join -1 1 -2 3 -o 2.1 2.2 2.3 2.4 2.5 2.6 1.2 1.3 fileA <(sort -k3 fileB) . Вы могли даже сохранить порядок строк в fileB и интервал, если Вы так желали, ищет мои сообщения под join отметьте, если Вам любопытно видеть как. –  don_crissti 26.09.2015, 18:56
  • 4
    Важный: FILE1 и FILE2 должны быть отсортированы на объединяющих полях. Это скорее единогласно уничтожает упорядочивание. join плохой инструмент для задачи; Вы не доказали иначе. –  Ricky Beam 26.09.2015, 22:56
  • 5
    @RickyBeam - в примере OP file1 уже отсортирован, хотя в целом оба должны быть отсортированы так, я полностью согласен здесь. Факт это sort "единогласно уничтожает упорядочивание", не важно, потому что можно обратиться вывод назад к начальному порядку. Таким образом, если Вы достаточно умны. Я не чувствую потребность доказать Вас что-либо, но здесь являюсь несколькими примерами для Вас для чтения 1,2,3. –  don_crissti 26.09.2015, 23:24

С массивом, согласно просьбе (полностью в bash)...

while read num loc; do A[0x$num]=$loc; done < A
while read B; do set -- $B; echo "${B} ${A[0x$3]}"; done < B

(работы в ударе v2)

Первая строка загружает массив "A" из файла A. 0x$num укусил, должен сохранить все в том же основании системы счисления иначе, начальные нули делают их восьмеричными. Вторая строка читает каждую строку файла B (сохраняющий пробелы), устанавливает позиционный args от той строки и наконец печатает строку плюс индексируемая запись от "A".

0
27.01.2020, 20:16

Вот сценарий Bash, который делает то, что Вы ищете. Сценарий звонил mergeAB.bash.

#!/bin/bash

readarray A < fileA.txt 

i=0
while read -r B; do
  idx=$(( $i % ${#A[@]} ))

  printf "%s %s" "$B" "${A[$idx]}"
  #echo "i: $i | A#: ${#A[@]} | IDX: $idx"

  let i=i+1
done < fileB.txt

Когда Вы выполняете его:

$ ./mergeAB.bash 
01-Dec-2013 01.664  001     AAA CAC 1083 001 Apple, CA
01-Dec-2013 01.664  020     AAA CAC 0513 020 Banana, CN
01-Dec-2013 01.668  023     AAA CAC 1091 023 Apple, LA
01-Dec-2013 01.668  101     AAA CAC 0183 045 Orange, TT
01-Dec-2013 01.674  200     AAA CAC 0918 101 Orange, OS
01-Dec-2013 01.674  045     AAA CAC 0918 200 Kiwi, AA
01-Dec-2013 01.664  001     AAA CAC 2573 001 Apple, CA
01-Dec-2013 01.668  101     AAA CAC 1091 020 Banana, CN
01-Dec-2013 01.668  020     AAA CAC 6571 023 Apple, LA
01-Dec-2013 01.668  023     AAA CAC 2148 045 Orange, TT
01-Dec-2013 01.674  200     AAA CAC 0918 101 Orange, OS
01-Dec-2013 01.668  045     AAA CAC 5135 200 Kiwi, AA

Подробнее

Самая первая вещь, которую мы делаем, использовать команду readarray считать содержание fileA.txt в массив. Это - более новая функция Bash 4.x, поэтому при использовании более старой версии Bash, можно использовать что-то вроде этого вместо этого:

$ IFS=$'\n' read -d '' -r -a A < fileA.txt

Остальная часть этого немного сложного сценария, но я оставил подробное echo в середине, которую можно не прокомментировать для наблюдения то, что продолжается.

$ ./mergeAB.bash | grep i:
i: 0 | A#: 6 | IDX: 0
i: 1 | A#: 6 | IDX: 1
i: 2 | A#: 6 | IDX: 2
i: 3 | A#: 6 | IDX: 3
i: 4 | A#: 6 | IDX: 4
i: 5 | A#: 6 | IDX: 5
i: 6 | A#: 6 | IDX: 0
i: 7 | A#: 6 | IDX: 1
i: 8 | A#: 6 | IDX: 2
i: 9 | A#: 6 | IDX: 3
i: 10 | A#: 6 | IDX: 4
i: 11 | A#: 6 | IDX: 5

Что продолжается здесь? Существует счетчик, $i то, что мы используем для подсчета каждой строки от fileB.txt поскольку мы циклично выполняемся через него. Мы затем вычисляем $idx путем вычисления подразделения по модулю текущего значения $i и количество строк в fileA.txt.

Примечание: длина массива A. Путем вычисления $idx этим путем мы можем сделать это "циклом" вокруг от 0 до 5, затем от 0 до 5 и т.д. В выводе отладки выше Вас видят это с IDX: столбец.

Остальная часть сценария является довольно стандартной, с помощью printf распечатать связанные строки от fileB.txt с соответствующей строкой от fileA.txt.

3
27.01.2020, 20:16
  • 1
    !! SIM, именно это я должен также узнать больше о нем –  JOSS 25.01.2014, 08:10
  • 2
    @JOSS - Вам довольно рады, спасибо за интересный Q! –  slm♦ 25.01.2014, 08:10
  • 3
    @SIM, я просто узнаю, что результат не соответствует..... файлу A –  JOSS 25.01.2014, 09:00
  • 4
    : число должно соответствовать к среднему числу из файла B., Вы знаете, как зафиксировать его?? –  JOSS 25.01.2014, 09:03

Теги

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