Присоедините два файла, добавив значения в определенные столбцы

-Dswt.autoScale=exact

работал для меня. По-видимому, он использовал настройку масштабирования шрифта Gnome Tweak Tool в 1,35. Параметры autoScale объясняются с помощью автоматического масштабирования SWT

3
задан 2 May 2018 в 17:03

10 ответов

Отвечая на ответ @ Jos: sqlite

db=$(mktemp) sqlite3 "$db" <<'END' create table f1 (v1 text,v2 text,v3 text,v4 text,v5 text,v6 text,v7 text,v8 text); create table f2 (v1 text,v2 text,v3 text,v4 text); .separator " " .import file1.txt f1 .import file2.txt f2 select f1.*, f2.v3, f2.v4 from f1,f2 where f1.v6=f2.v1 and f1.v7=f2.v2; END rm "$db"

или почти с одним лайнером:

sqlite3 -separator " " <<'END' create table f1 (v1, v2, v3, v4, v5, v6, v7, v8 ); create table f2 (v1, v2, v3, v4); .import file1.txt f1 .import file2.txt f2 select f1.*, f2.v3, f2.v4 from f1,f2 where f1.v6=f2.v1 and f1.v7=f2.v2; END
5
ответ дан 17 July 2018 в 15:27

bash: я позволил удалить пустые строки из файлов.

declare -A keys while read -r k1 k2 value; do keys[$k1,$k2]=$value done < file2.txt while read -ra fields; do key="${fields[5]},${fields[6]}"; echo "${fields[*]} ${keys[$key]}" done < file1.txt 1 1 1 1 1 5 9 1 A B 2 2 2 2 2 7 8 2 C D 3 3 3 3 3 7 7 3 G H 4 4 4 4 4 8 6 4 E F
2
ответ дан 17 July 2018 в 15:27

Я знаю, что вы не запрашивали решение для базы данных, но если у вас есть сервер MySQL, вот как это сделать:

create table file1 (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int); create table file2 (c1 int, c2 int, c3 char, c4 char); load data infile 'file1' into table file1 fields terminated by ' '; load data infile 'file2' into table file2 fields terminated by ' '; select f1.*, f2.c3, f2.c4 from file1 as f1 join file2 as f2 on f1.c6 = f2.c1 and f1.c7 = f2.c2 order by f1.c1;

(мне пришлось снять пробел )

Результат:

+------+------+------+------+------+------+------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c3 | c4 | +------+------+------+------+------+------+------+------+------+------+ | 1 | 1 | 1 | 1 | 1 | 5 | 9 | 1 | A | B | | 2 | 2 | 2 | 2 | 2 | 7 | 8 | 2 | C | D | | 3 | 3 | 3 | 3 | 3 | 7 | 7 | 3 | G | H | | 4 | 4 | 4 | 4 | 4 | 8 | 6 | 4 | E | F | +------+------+------+------+------+------+------+------+------+------+ 4 rows in set (0,00 sec)
5
ответ дан 17 July 2018 в 15:27

Это будет работать, хотя я уверен, что кто-то придумает намного лучшее однострочное awk решение.

cp file1.txt output.txt && while read -r file2_line; do # Empty line --> continue [[ -z "$file2_line" ]] && continue # Find matching line file1_matching_line=$(grep -n "$(echo "$file2_line" | cut -d' ' -f 1,2)" <(cut -d' ' -f6,7 output.txt) | grep -Po "^[0-9]+"); # no find? continue! [[ ! $? -eq 0 ]] && continue # Add the fields 3 and 4 of file2 to the end of the matching line of output.txt echo "$file1_matching_line" | while read -r ml; do sed -i "${ml}s/$/ $(echo "$file2_line" | cut -d' ' -f 3,4)/" output.txt done done < file2.txt && cat output.txt

Магия происходит в строке:

file1_matching_line=[...]

Найдите номер строки (-n) всех вхождений полей 1 и 2 файла 2

$(echo "$file2_line" | cut -d' ' -f 1,2)

в файле output.txt, который является копией файла file1.txt

<(cut -d' ' -f6,7 output.txt)
1
ответ дан 17 July 2018 в 15:27

Используйте awk

awk 'NR==FNR{ seen[$1FS$2]=$3FS$4; next } { print $0, seen[$6FS$7] }' file2 file1

и для удаления пустых строк с выхода:

awk 'NR==FNR{ seen[$1FS$2]=$3FS$4; next } NF{ print $0, seen[$6FS$7] }' file2 file1

или имена небольших пробелов и разумных переменных идут далеко вперед в сторону удобочитаемости. Кроме того, воспользуйтесь запятой в ключе массива

awk ' NR == FNR {value[$1,$2] = $3 OFS $4; next} {print $0, value[$6,$7]} ' file2.txt file1.txt NR установлено значение 1, когда первая запись будет считана awk и будет увеличиваться для каждого следующего чтения записей либо в одном или нескольких входных файлах, пока все прочитанные не будут завершены. FNR устанавливается в 1, когда первая запись считывается awk и увеличивается для каждого следующего чтения записей в текущем файле и возвращается к 1 для следующего входного файла, если несколько входных файлов. поэтому NR == FNR всегда является истинным условием, и блок, за которым следует это, будет выполнять действия только для первого файла. [F8] - связанный массив awk с комбинацией клавиш столбца $ 1 и столбца $ 2 со значением столбца $ 3 и столбца $ 4. Маркер next пропускает выполнение остальных команд, и они будут выполняться только для следующего файла (ов), кроме первого. [F10]; предварительное задание числа полей в записи, где поля известны и разделены полевым разделителем FS; поэтому FS между столбцами используется для инсталляции разделителя полей, иначе вы можете использовать запятую , внутри массива. так что это NF{ print $0, seen[$6FS$7] }, напечатать текущую запись $0 в файле1 и значение, сопоставляемое с столбцом $ 6 и столбцом $ 7, присутствующим в массиве, если это не пустая строка.
6
ответ дан 17 July 2018 в 15:27

отвечая на ответ @Йос таких данных SQLite

db=$(mktemp) sqlite3 "$db" <<'END' create table f1 (v1 text,v2 text,v3 text,v4 text,v5 text,v6 text,v7 text,v8 text); create table f2 (v1 text,v2 text,v3 text,v4 text); .separator " " .import file1.txt f1 .import file2.txt f2 select f1.*, f2.v3, f2.v4 from f1,f2 where f1.v6=f2.v1 and f1.v7=f2.v2; END rm "$db"

или в почти-один-лайнер путь:

sqlite3 -separator " " <<'END' create table f1 (v1, v2, v3, v4, v5, v6, v7, v8 ); create table f2 (v1, v2, v3, v4); .import file1.txt f1 .import file2.txt f2 select f1.*, f2.v3, f2.v4 from f1,f2 where f1.v6=f2.v1 and f1.v7=f2.v2; END
5
ответ дан 23 July 2018 в 16:24
  • 1
    @glenjackman, все "текст" можно удалить: create table f2 (v1, v2 ,v3 ,v4 ); – JJoao 17 May 2018 в 12:07
  • 2
    Итак, если вы не укажете файл db, то вы в памяти? – glenn jackman 17 May 2018 в 14:49
  • 3
    Гленн Джекман, да! (sqlite всегда удивляет меня!) И если таблица не была создана, .import создает ее и использует первую строку как имена полей! – JJoao 17 May 2018 в 20:28

баш: я взял на себя смелость убрать пустые строки из файлов.

declare -A keys while read -r k1 k2 value; do keys[$k1,$k2]=$value done < file2.txt while read -ra fields; do key="${fields[5]},${fields[6]}"; echo "${fields[*]} ${keys[$key]}" done < file1.txt 1 1 1 1 1 5 9 1 A B 2 2 2 2 2 7 8 2 C D 3 3 3 3 3 7 7 3 G H 4 4 4 4 4 8 6 4 E F
2
ответ дан 23 July 2018 в 16:24

Я знаю, что вы не запрашивали решение для базы данных, но если у вас есть сервер MySQL, вот как это сделать:

create table file1 (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int); create table file2 (c1 int, c2 int, c3 char, c4 char); load data infile 'file1' into table file1 fields terminated by ' '; load data infile 'file2' into table file2 fields terminated by ' '; select f1.*, f2.c3, f2.c4 from file1 as f1 join file2 as f2 on f1.c6 = f2.c1 and f1.c7 = f2.c2 order by f1.c1;

(мне пришлось снять пробел )

Результат:

+------+------+------+------+------+------+------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c3 | c4 | +------+------+------+------+------+------+------+------+------+------+ | 1 | 1 | 1 | 1 | 1 | 5 | 9 | 1 | A | B | | 2 | 2 | 2 | 2 | 2 | 7 | 8 | 2 | C | D | | 3 | 3 | 3 | 3 | 3 | 7 | 7 | 3 | G | H | | 4 | 4 | 4 | 4 | 4 | 8 | 6 | 4 | E | F | +------+------+------+------+------+------+------+------+------+------+ 4 rows in set (0,00 sec)
5
ответ дан 23 July 2018 в 16:24

Это будет работать, хотя я уверен, что кто-то придумает намного лучшее однострочное awk решение.

cp file1.txt output.txt && while read -r file2_line; do # Empty line --> continue [[ -z "$file2_line" ]] && continue # Find matching line file1_matching_line=$(grep -n "$(echo "$file2_line" | cut -d' ' -f 1,2)" <(cut -d' ' -f6,7 output.txt) | grep -Po "^[0-9]+"); # no find? continue! [[ ! $? -eq 0 ]] && continue # Add the fields 3 and 4 of file2 to the end of the matching line of output.txt echo "$file1_matching_line" | while read -r ml; do sed -i "${ml}s/$/ $(echo "$file2_line" | cut -d' ' -f 3,4)/" output.txt done done < file2.txt && cat output.txt

Магия происходит в строке:

file1_matching_line=[...]

Найдите номер строки (-n) всех вхождений полей 1 и 2 файла 2

$(echo "$file2_line" | cut -d' ' -f 1,2)

в файле output.txt, который является копией файла file1.txt

<(cut -d' ' -f6,7 output.txt)
1
ответ дан 23 July 2018 в 16:24

Используйте awk

awk 'NR==FNR{ seen[$1FS$2]=$3FS$4; next } { print $0, seen[$6FS$7] }' file2 file1

и для удаления пустых строк с выхода:

awk 'NR==FNR{ seen[$1FS$2]=$3FS$4; next } NF{ print $0, seen[$6FS$7] }' file2 file1

или имена небольших пробелов и разумных переменных идут далеко вперед в сторону удобочитаемости. Кроме того, воспользуйтесь запятой в ключе массива

awk ' NR == FNR {value[$1,$2] = $3 OFS $4; next} {print $0, value[$6,$7]} ' file2.txt file1.txt NR установлено значение 1, когда первая запись будет считана awk и будет увеличиваться для каждого следующего чтения записей либо в одном или нескольких входных файлах, пока все прочитанные не будут завершены. FNR устанавливается в 1, когда первая запись считывается awk и увеличивается для каждого следующего чтения записей в текущем файле и возвращается к 1 для следующего входного файла, если несколько входных файлов. поэтому NR == FNR всегда является истинным условием, и блок, за которым следует это, будет выполнять действия только для первого файла. [F8] - связанный массив awk с комбинацией клавиш столбца $ 1 и столбца $ 2 со значением столбца $ 3 и столбца $ 4. Маркер next пропускает выполнение остальных команд, и они будут выполняться только для следующего файла (ов), кроме первого. [F10]; предварительное задание числа полей в записи, где поля известны и разделены полевым разделителем FS; поэтому FS между столбцами используется для инсталляции разделителя полей, иначе вы можете использовать запятую , внутри массива. так что это NF{ print $0, seen[$6FS$7] }, напечатать текущую запись $0 в файле1 и значение, сопоставляемое с столбцом $ 6 и столбцом $ 7, присутствующим в массиве, если это не пустая строка.
6
ответ дан 23 July 2018 в 16:24

Другие вопросы по тегам:

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