Необходимо извлечь 2 строки из определенных строк нескольких файлов и распечатать в новый файл, разделенные табуляцией

С grep :

grep -c '^[^,]*,[^0]' 

Это работает, только если 2-й столбец сформирован как целое число, но не -0 , +0 . Для более общего случая см. @ Ответ Стефана Хазеласа .

3
13.01.2017, 00:27
5 ответов

Вы можете использовать sed в цикле для каждого файла в вашей текущей папке. Вы извлекаете соответствующие части и добавляете их через >> в файл с именем file следующим образом:

for files in *; \
do sed -n -e '/^From file/ H;' \
          -e '/Ratio of morphemes over utterances/ {H; x; s/\n//g; s/From file <\(.*\)>.*Ratio of morphemes over utterances = \([0-9]*\.[0-9]*\).*/\1:    \2/g; p;}' "$files";
done >>file
4
27.01.2020, 21:12

Вам не нужен цикл. Большинство инструментов обработки текста принимают несколько аргументов, например с sed :

sed '/From file/{s/.*<\(.*\)>/\1/;h
}
/Ratio of morphemes over utterances/!d
s/.*= //;H;x;s/\n/\t/' ./* > outfile

Это извлекает имя файла и сохраняет его в буфере хранения, удаляет все строки, кроме тех, где извлекается "коэффициент", который он добавляет к имени файла, а затем обменивается буферами и заменяет новую строку табуляцией. Конечно, \ t специфичен для gnu sed , поэтому замените его буквенной вкладкой (в терминале нажмите Ctrl + V , затем ] Вкладка ), если вы не используете установку GNU . Еще быстрее, с любым sed :

sed '/From file/{s/.*<\(.*\)>/\1/;h
}
/Ratio of morphemes over utterances/!d
s/.*= //;H;x' ./* | paste - - > outfile

Если ваши файлы огромны, вы можете выйти при втором совпадении (строка с «соотношением») и перейти к следующему файлу. Здесь пригодится nextfile gawk (я думаю, что это POSIX, но не уверен, какие варианты awk его поддерживают ...):

awk '/From file/{printf("%s\t", substr($3, 2, length($3)-2))}
/Ratio of morphemes over utterances/{print $7; nextfile}' ./* > outfile
1
27.01.2020, 21:12
perl -0nE 'say "$1\t$2" if /From file <(.*?)>.*over utterances = (\d\S*)/s' * > out
1
27.01.2020, 21:12

вы можете попробовать с помощью команды awk

awk '/Ratio of morphemes over utterances/{print FILENAME,$NF;next}' *.cha

, если вы хотите извлечь имя файла из шаблона из файла

, затем попробуйте следующую команду awk.

awk '/From file/{filename=$NF} filename && /Ratio of morphemes over utterances/{print FILENAME,$NF;filename="";next}' *.txt
0
27.01.2020, 21:12

Поскольку вы упомянули, что знакомы с Python, вот скрипт python, который может выполнить эту работу:

#!/usr/bin/env python
from __future__ import print_function
import os,re,sys

def read_file(filepath):
    with open(filepath) as fd:
         for line in fd:
             clean_line = line.strip()

             if 'From file' in clean_line:

                 words = re.split('<|>| ', clean_line)
                 print(words[-2],end=" ")

             if 'Ratio of morphemes over utterances' in clean_line:
                 print(clean_line.split('=')[-1])



def find_files(treeroot):
    selfpath = os.path.abspath(__file__)
    for dir,subdirs,files in os.walk(treeroot):
         for f in files: 
             filepath = os.path.abspath(os.path.join(dir,f))
             if selfpath  ==  filepath: continue
             try:
                 read_file(filepath)
             except IOError:
                 pass
def main():
    directory = '.'
    if len(sys.argv) == 2:
       directory = sys.argv[1]
    find_files(os.path.abspath(directory))

if __name__ == '__main__': main()

Пример выполнения:

$ ./extract_data.py                                                                                               
adam02.cha  2.547
adam01.cha  2.213

Это работает просто: мы используем os.walk для рекурсивного обхода каталога, нахождения всех файлов и исключения самого скрипта, и для каждого файла мы запускаем функцию read_file () , которая считывает каждый файл построчно и находит соответствующие поля. re.split () используется для более удобного разбиения строки имени файла на список слов, используя пробел и < и > в качестве разделителей слов. Сценарий может принимать аргумент командной строки для каталога, но если он не указан, предполагается текущий рабочий каталог. Таким образом, вы можете запускать скрипт по пути или из каталога, в котором хранятся файлы.Что касается создания нового файла со всеми данными, это тривиально - используйте перенаправление оболочки как ./ extract_data.py> /path/to/new_file.txt. Предупреждение - перенаправьте сценарий в файл, расположенный в другом каталоге, поскольку новый файл может быть помещен в очередь в os.walk () и нарушить сценарий. Дополнительным улучшением является то, что вы можете вызывать цикл for для файлов как для f в sorted (files): , чтобы читать файлы в отсортированном виде.

1
27.01.2020, 21:12

Теги

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