Вставьте новые строки с отсутствующими значениями (NA)

Я хотел бы вставить новые строки в текстовые файлы, если отсутствуют значения. У меня есть, например, следующий текстовый файл (A.txt), для которого отсутствует строка 5. Кроме того, поскольку файл должен иметь 12 строк, строки 11-12 также отсутствуют.

1 2.30 2 3.01 3 3.22 4 3.34 6 3.01 7 2.90 8 2.99 9 3.00 10 3.02 

Мой ожидаемый результат следующий. Для отсутствующих случаев следует добавить строку с номером и NA. Как вы видите, это произошло по желанию в строках 5, 11 и 12:

 1 2.30 2 3.01 3 3.22 4 3.34 5 NA 6 3.01 7 2.90 8 2.99 9 3.00 10 3.02 11 NA 12 NA 

Я могу сделать это, используя следующий скрипт:

 f1=/my-directory/ echo "new file" > "$f1"/newfile.txt for i in {1..12}; do l=$(awk '{print $1}' /"$f1"/A.txt | grep -wE ^$i /"$f1"/A.txt) if grep --quiet -wE ^$i /"$f1"/A.txt; then echo "$l" >> "$f1"/newfile.txt; else echo "$i NA" >> "$f1"/newfile.txt; fi done 

Это прекрасно работает. Проблема в том, что мне нужно сделать это примерно для 600 файлов, содержащих более 160000 строк. Таким образом, решение цикла потребует слишком много времени для поиска по всем линиям. Мой вопрос: есть ли более простое решение, которое может это сделать?

5 Solutions collect form web for “Вставьте новые строки с отсутствующими значениями (NA)”

Вы можете сделать это с помощью awk скрипта:

 awk '{ while (NR + shift < $1) { print (NR + shift) " NA"; shift++ }; print } END { shift++; while (NR + shift < 13) { print (NR + shift) " NA"; shift++ } }' /tmp/test1 

будет выдавать требуемый результат для /tmp/test1 (замените это на каждый файл, который вы хотите обработать).

В более читаемой форме:

 #!/usr/bin/awk -f { while (NR + shift < $1) { print (NR + shift) " NA" shift++ } print } END { shift++ while (NR + shift < 13) { print (NR + shift) " NA" shift++ } } 

Сохраните это как файл, скажем, fill-missing , сделайте его исполняемым, тогда вы можете просто запустить

 ./fill-missing /tmp/test1 

Скрипт обрабатывает каждую строку, отслеживая ожидаемую дельта с текущим номером строки в shift . Поэтому для каждой строки, если текущая строка не соответствует первому номеру в строке, она печатает соответствующий номер строки, а затем NA и увеличивает дельта; как только номера строк совпадают, он печатает текущую строку. В конце процесса он печатает любые недостающие строки, необходимые для достижения 12.

здесь хорошо работает:

 join -a 1 -o 0,2.2 -e NA <(seq 12) A.txt 2>/dev/null 

Я выбрасываю stderr, потому что join жалуется, если поле объединения не лексически отсортировано.

файл awk

 BEGIN { i=1 ; } function upto(x) { while (i<x) printf "%d NA\n",i++ ;} { if ( $1 == i ) print ; upto($1) ; i++ ;} END { upto(final+1) ;} 

называться

 awk -f nl.awk -v final=12 /tmp/test1 

весь цикл

 cd /my/directory ls | while read f do awk -f ~/nl.awk -v final=12 $f > /an/other/dir/$f done 

где

  • вы помещаете awk-программу в свой файл $ HOME ( ~/nl.awk )

Вы также можете попробовать Python:

 #!/usr/bin/env python2 with open('file.txt') as f: check = 0 for line in f: if int(line.split()[0]) == check + 1: check = int(line.split()[0]) print line.rstrip() else: check = int(line.split()[0]) print int(line.split()[0]) - 1, 'NA' print line.rstrip() print int(line.split()[0]) + 1, 'NA' print int(line.split()[0]) + 2, 'NA' 

Здесь мы сравниваем номер строки int(line.split()[0]) с check + 1 , мы установили начальное значение check как 0 . Если значения равны, мы напечатали линию, иначе мы напечатали желаемый контент, т. Е. Номер нужной строки и NA . Последние две строки используются для печати 11-й и 12-й строк.

Glenn Jackman's bash и метод join с несколькими настройками, эта функция получает счет из входного файла и использует это значение как значение по умолчанию:

 # Usage: inlwmv file [ missing_value [ extra_lines ] ] # if unset, missing_value="NA", and extra_lines=0 inlwmv() { join -a 1 -o 0,2.2 -e "${2:-NA}" \ <(seq $((${3:-0} + $(tail -n 1 "$1" | cut -d ' ' -f1))) | sort -k 1b,1) \ <(sort -k 1b,1 "$1") | \ sort -g ; } 

Для вопроса ОП:

 inlwmv A.file "" 2 

Для этого дублированного вопроса версия Jackman терпит неудачу при последнем значении файла , ( join довольно тонкое в отношении порядка, но использование sort три раза заставляет его вести себя по мере необходимости):

 inlwmv afile 0 
  • как подражать «замените abb a» на sed?
  • sed -e 's / ^ //' не работает для первой строки
  • Curl url txt file, но grep каждый URL отдельно от одного файла
  • Каковы альтернативные инструменты для поиска файлов в полном объеме?
  • Как sed заменить этот конец линии?
  • Как связывать линии между шаблоном начала и конца?
  • использование sed для замены шаблона с помощью хэш-значений
  • распечатать определенную строку из нескольких файлов
  • sed или tr однострочный, чтобы удалить все числовые цифры
  • Соедините каждую строку файла с определенной переменной во второй команде
  • Удалить строки, начинающиеся с #
  • Interesting Posts

    Супер-медленная скорость локальной сети, если только скачивание через FTP-клиент Chrome

    su или sudo сохранение / удаление определенных переменных среды

    Как показать значки рабочего стола в элементарной ОС?

    Оболочка сценария скрипта условно

    Что могло привести к тому, что исполняемые файлы g ++ (и clang ++) перестали работать?

    Отфильтровать несколько элементов из вывода длинной команды

    Получить последнюю минуту из строк из списка

    файл (1) и магия (5): описание других форматов

    Какой процесс отправляет TCP SYN на Solaris 10?

    Расширение переменной оболочки и эффект glob и разбиение на нее

    Есть ли утилита для шифрования файла с помощью ключа, который я создал?

    Существуют ли дистрибутивы Linux, специально предназначенные для обучения Linux?

    Динамическое имя файла не работает в rsyslog

    Как я могу определить, какое устройство или имя файла я перенаправляю

    Как я могу постоянно изменять переменные среды через терминал? (Ubuntu 16.04)

    Linux и Unix - лучшая ОС в мире.