Массовое преобразование чисел в текстовые файлы с использованием sed

В настоящее время у меня есть несколько файлов с миллионами строк, которые выглядят следующим образом:

565 0 10 12 23 18 17 25 564 1 7 12 13 16 18 40 29 15

Номера 565 и 564 являются идентификаторами, и я извлек все уникальные идентификаторы из разных файлов и объединил их в один файл, выглядящий следующим образом:

565 564 182 982

Далее, я хочу провести следующее преобразование чисел в исходных файлах:

565 -> 1 564 -> 2 182 -> 3 982 -> 4

, так что исходные файлы будут выглядеть так:

1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15

Я знаю, как применять одно преобразование с помощью sed, но есть ли способы указать способ преобразования в текстовом файле и использовать сценарий оболочки для примените его к исходным файлам?

Спасибо.

1
задан 6 June 2017 в 13:43

6 ответов

Если вы хотите монотонно наращивать первое поле, вам не нужно использовать дополнительный файл для сопоставления или первого поля, просто используйте awk, чтобы установить первое поле в качестве номера строки (записи):

awk '{$1=NR} 1' file.txt

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

Теперь, вот способы решения вашей проблемы, когда у вас есть дополнительный файл, скажем, id.txt с первыми полями:

Вам было бы лучше использовать то, что может понять номер строки и отслеживать их, например awk:

awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt
Предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt - основной файл NR==FNR {a[$0]=NR; next} сохраняет каждую запись файла id.txt в качестве ключа ассоциативного массива a со значением, являющимся соответствующим номером строки. next не гарантирует, что дальнейшая обработка записей id.txt {$1=a[$1]} устанавливает первое поле в значение соответствующего элемента массива; обратите внимание, что в этом есть предостережение по восстановлению всей записи с пространством в качестве разделителя, но я предполагаю, что в этом случае мы можем использовать эту краткость. 1 является просто заполнителем для интерпретации true, так что вся запись печатается впоследствии

Если вы чувствуете себя странно, вы можете использовать некоторые стандартные инструменты * nix, с помощью из подстановки процесса (<()) из bash и paste наконец:

paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt) 
, предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt является основным файлом

Предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt - основной файл

cut -d' ' -f2- file.txt получает все поля но первый

% cat file.txt                                               
565 0 10 12 23 18 17 25
564 1 7 12 13 16 18 40 29 15
182 10 12 23 18 17 25
892 1 7 12 13 16 18 40 29 15

% awk '{$1=NR} 1' file.txt
1 0 10 12 23 18 17 25
2 1 7 12 13 16 18 40 29 15
3 10 12 23 18 17 25
4 1 7 12 13 16 18 40 29 15

% cat id.txt                                                 
565
564
182
892

% awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt
1 0 10 12 23 18 17 25
2 1 7 12 13 16 18 40 29 15
3 10 12 23 18 17 25
4 1 7 12 13 16 18 40 29 15

% paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt) 
 1 0 10 12 23 18 17 25
 2 1 7 12 13 16 18 40 29 15
 3 10 12 23 18 17 25
 4 1 7 12 13 16 18 40 29 15
1
ответ дан 22 May 2018 в 21:49

Если вы хотите монотонно наращивать первое поле, вам не нужно использовать дополнительный файл для сопоставления или первого поля, просто используйте awk, чтобы установить первое поле в качестве номера строки (записи):

awk '{$1=NR} 1' file.txt

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

Теперь, вот способы решения вашей проблемы, когда у вас есть дополнительный файл, скажем, id.txt с первыми полями:

Вам было бы лучше использовать то, что может понять номер строки и отслеживать их, например awk:

awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt Предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt - основной файл NR==FNR {a[$0]=NR; next} сохраняет каждую запись файла id.txt в качестве ключа ассоциативного массива a со значением, являющимся соответствующим номером строки. next не гарантирует, что дальнейшая обработка записей id.txt {$1=a[$1]} устанавливает первое поле в значение соответствующего элемента массива; обратите внимание, что в этом есть предостережение по восстановлению всей записи с пространством в качестве разделителя, но я предполагаю, что в этом случае мы можем использовать эту краткость. 1 является просто заполнителем для интерпретации true, так что вся запись печатается впоследствии

Если вы чувствуете себя странно, вы можете использовать некоторые стандартные инструменты * nix, с помощью из подстановки процесса (<()) из bash и paste наконец:

paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt) , предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt является основным файлом

Предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt - основной файл

cut -d' ' -f2- file.txt получает все поля но первый

% cat file.txt 565 0 10 12 23 18 17 25 564 1 7 12 13 16 18 40 29 15 182 10 12 23 18 17 25 892 1 7 12 13 16 18 40 29 15 % awk '{$1=NR} 1' file.txt 1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15 3 10 12 23 18 17 25 4 1 7 12 13 16 18 40 29 15 % cat id.txt 565 564 182 892 % awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt 1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15 3 10 12 23 18 17 25 4 1 7 12 13 16 18 40 29 15 % paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt) 1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15 3 10 12 23 18 17 25 4 1 7 12 13 16 18 40 29 15
1
ответ дан 18 July 2018 в 12:04

Если вы хотите монотонно наращивать первое поле, вам не нужно использовать дополнительный файл для сопоставления или первого поля, просто используйте awk, чтобы установить первое поле в качестве номера строки (записи):

awk '{$1=NR} 1' file.txt

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

Теперь, вот способы решения вашей проблемы, когда у вас есть дополнительный файл, скажем, id.txt с первыми полями:

Вам было бы лучше использовать то, что может понять номер строки и отслеживать их, например awk:

awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt Предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt - основной файл NR==FNR {a[$0]=NR; next} сохраняет каждую запись файла id.txt в качестве ключа ассоциативного массива a со значением, являющимся соответствующим номером строки. next не гарантирует, что дальнейшая обработка записей id.txt {$1=a[$1]} устанавливает первое поле в значение соответствующего элемента массива; обратите внимание, что в этом есть предостережение по восстановлению всей записи с пространством в качестве разделителя, но я предполагаю, что в этом случае мы можем использовать эту краткость. 1 является просто заполнителем для интерпретации true, так что вся запись печатается впоследствии

Если вы чувствуете себя странно, вы можете использовать некоторые стандартные инструменты * nix, с помощью из подстановки процесса (<()) из bash и paste наконец:

paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt) , предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt является основным файлом

Предполагая, что id.txt содержит только извлеченные первые столбцы, а file.txt - основной файл

cut -d' ' -f2- file.txt получает все поля но первый

% cat file.txt 565 0 10 12 23 18 17 25 564 1 7 12 13 16 18 40 29 15 182 10 12 23 18 17 25 892 1 7 12 13 16 18 40 29 15 % awk '{$1=NR} 1' file.txt 1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15 3 10 12 23 18 17 25 4 1 7 12 13 16 18 40 29 15 % cat id.txt 565 564 182 892 % awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt 1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15 3 10 12 23 18 17 25 4 1 7 12 13 16 18 40 29 15 % paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt) 1 0 10 12 23 18 17 25 2 1 7 12 13 16 18 40 29 15 3 10 12 23 18 17 25 4 1 7 12 13 16 18 40 29 15
1
ответ дан 24 July 2018 в 19:54
awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed ids.txt

Он будет читать ваш файл «ids» и создает список идентификаторов для поиска и замены с помощью sed.

$ cat pattern.sed 
s/^564/1/
s/^565/2/
...

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

sort ids.txt | uniq | awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed 

, чтобы сделать его более эффективным, затем запустите:

$ sed -i.bk -f pattern.sed file 

$ cat file
2 0 10 12 23 18 17 25
1 1 7 12 13 16 18 40 29 15
1 1 7 12 13 16 18 40 29 11111
1 1 7 12 13 16 18 40 29 15555
2 0 10 12 23 18 17 2555
...

Если вы хотите сортировать конечный файл, используйте sort -k1,1 file > file.sorted.

0
ответ дан 22 May 2018 в 21:49
awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed ids.txt

Он будет читать ваш файл «ids» и создает список идентификаторов для поиска и замены с помощью sed.

$ cat pattern.sed s/^564/1/ s/^565/2/ ...

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

sort ids.txt | uniq | awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed

, чтобы сделать его более эффективным, затем запустите:

$ sed -i.bk -f pattern.sed file $ cat file 2 0 10 12 23 18 17 25 1 1 7 12 13 16 18 40 29 15 1 1 7 12 13 16 18 40 29 11111 1 1 7 12 13 16 18 40 29 15555 2 0 10 12 23 18 17 2555 ...

Если вы хотите сортировать конечный файл, используйте sort -k1,1 file > file.sorted.

0
ответ дан 18 July 2018 в 12:04
awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed ids.txt

Он будет читать ваш файл «ids» и создает список идентификаторов для поиска и замены с помощью sed.

$ cat pattern.sed s/^564/1/ s/^565/2/ ...

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

sort ids.txt | uniq | awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed

, чтобы сделать его более эффективным, затем запустите:

$ sed -i.bk -f pattern.sed file $ cat file 2 0 10 12 23 18 17 25 1 1 7 12 13 16 18 40 29 15 1 1 7 12 13 16 18 40 29 11111 1 1 7 12 13 16 18 40 29 15555 2 0 10 12 23 18 17 2555 ...

Если вы хотите сортировать конечный файл, используйте sort -k1,1 file > file.sorted.

0
ответ дан 24 July 2018 в 19:54

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

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