Как получить конкретный текст из файла?

Я создал файл данных в следующем формате:

0.1
Analytic value = 340.347685734
Approximated value = 332.45634555
--
0.2
Analytic value = 340.936745872
Approximated value = 332.57893789
--
0.3
... and so on

Я хочу построить аналитические и приблизительные значения в matplotlib/gnuplot в зависимости от входного параметра (0,1, 0,2 и т. д.). Обычно перед созданием файла данных я использую для их создания скрипт awk, который помещает три значения в три столбца, что очень легко построить. Однако здесь я случайно сгенерировал файл данных в другом формате. Как я могу преобразовать этот текстовый файл в следующий (возможно, используя регулярное выражение или awk!):

0.1 340.347685734 332.45634555 
0.2 340.936745872 332.57893789
0.3 ... and so on

Или есть способ построить данные без преобразования формата с помощью gnuplot/matplotlib?

Обновлено: Я попытался сделать это с помощью python3. Ниже приведен мой код:

file = open("myFile.dat",'r')
newFile = open("newFile.dat", 'a')
for i in range(4000):
  col1 = file.readline().split[-1]
  col2 = file.readline().split[-1]
  col3 = file.readline().split[-1]
  _ = file.readline().split[-1]
  line = col1 + " " + col2 + " " + col3
  newFile.write(line)

Однако я получил некоторую ошибку TypeError: 'builtin_function_or_method' object is not subscriptable, которую я не понял, и я думаю, что это очень неэффективный код. Поэтому я и спросил в SE. Все решения, представленные до сих пор, работают достаточно хорошо. Я отметил решение awk как принятый ответ, потому что оно простое и элегантное. Кроме того, я ценю решение, использующее только gnuplot, которое также раскрывает для меня одну сторону gnuplot.

Попробуйте это: awk '/^[0-9]+\.[0-9]+$/ {val = $0} /Analytic value =/ {split($0, a, " = "); analytic = a[3]} /Approximated value =/ {split($0, a, " = "); approx = a[3]; print val, analytic, approx}' your_file > output_file

Obaskly 07.06.2023 18:51

Выглядит достаточно легко сделать с Regex. В чем проблема придумать регулярное выражение, которое это делает?

Thomas Weller 07.06.2023 18:51

Даже Regex вообще не нужен. 1. Замените Analytic value = ничем. 2. Замените Approximated value = ничем. 3. Замените \n пробелом. 4. Замените -- на \n

Thomas Weller 07.06.2023 18:52

Пожалуйста, отредактируйте свой вопрос (без комментариев): Что вы искали и что нашли? Что вы пробовали, и как это не удалось?

Cyrus 07.06.2023 19:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
74
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Здесь не нужно регулярное выражение. Всего 4 простых замены:

Две замены для нежелательного текста, одна замена для удаления разрывов строк и одна замена для повторной вставки разрыва строки.

file = """0.1
Analytic value = 340.347685734
Approximated value = 332.45634555
--
0.2
Analytic value = 340.936745872
Approximated value = 332.57893789
--
0.3
... and so on
"""

file = file.replace("Analytic value = ","")
file = file.replace("Approximated value = ","")
file = file.replace("\n"," ")
file = file.replace("-- ","\n")
print(file)

Результат:

0.1 340.347685734 332.45634555 
0.2 340.936745872 332.57893789 
0.3 ... and so on 
Ответ принят как подходящий

Я бы использовал GNU AWK для этой задачи следующим образом, пусть file.txt контент будет

0.1
Analytic value = 340.347685734
Approximated value = 332.45634555
--
0.2
Analytic value = 340.936745872
Approximated value = 332.57893789
--

затем

awk '/^--$/{print "";next}{printf "%s ",$NF}' file.txt

нет вывода

0.1 340.347685734 332.45634555 
0.2 340.936745872 332.57893789

Объяснение: для строки -- просто напечатайте новую строку и перейдите к следующей, для всех остальных строк выведите последнее поле, за которым следует пробел, а не новую строку. Если вы хотите узнать больше о NF, прочитайте 8 мощных встроенных переменных Awk — FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

(проверено в GNU Awk 5.1.0)

Есть много способов решить эту проблему, и выбор, среди прочего, будет зависеть от размера файла. Вот простое решение для случая, когда вы не можете загрузить весь файл сразу - вам нужно обрабатывать его построчно,

raw_data_file = 'data.txt'
out_data_file = 'data_final.txt'

counter = 0
with open(raw_data_file, 'r') as fin, open(out_data_file, 'w') as fout:
    temp_line = []
    for line in fin:

        if counter == 0:
            # First column
            temp_line.append(line.strip())
            counter += 1
            continue
        elif counter == 1:
            # Analytic value column
            temp_line.append(line.strip().split()[-1])
            counter += 1
            continue
        elif counter == 2:
            # Approximate value column
            temp_line.append(line.strip().split()[-1])
            counter += 1
        elif counter == 3:
            # Skip the -- and reset the counter
            counter = 0
            continue

        # Write the rearranged data to file
        fout.write((' ').join(temp_line))
        fout.write('\n')
        temp_line = []

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

Или есть способ построить данные без преобразования формата с помощью gnuplot/matplotlib?

Да, есть! Вот независимое от платформы решение только для gnuplot. Нет необходимости во внешних дополнительных инструментах подготовки данных.

Если вы рисуете из файла, пропустите раздел $Data <<EOD ... EOD и используйте plot 'yourFile.dat' ... .

Скрипт: (работает для gnuplot>=5.0.6, март 2017 г.)

### plot special data format
reset session

$Data <<EOD
0.1
Analytic value = 340.347685734
Approximated value = 332.45634555
--
0.2
Analytic value = 340.936745872
Approximated value = 332.57893789
--
0.3
Analytic value = 341.936745872
Approximated value = 333.57893789
EOD

set datafile missing NaN
set key out
myFilter(colD,colF,valF) = strcol(colF) eq valF ? column(colD) : NaN

plot $Data u (valid(1)?x0=$1:x0):(myFilter(4,1,"Analytic"))     w lp pt 7 lc "red"  ti "analytic", \
        '' u (valid(1)?x0=$1:x0):(myFilter(4,1,"Approximated")) w lp pt 7 lc "blue" ti "approximated"
### end of script

Результат:

Используя любой awk:

$ awk '{n=(NR%4); val[n]=$NF} n==0{print val[1], val[2], val[3]}' file
0.1 340.347685734 332.45634555
0.2 340.936745872 332.57893789

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