Экспорт текста в csv с использованием первого и последнего столбца

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

28/03/2023 NETBANKING TRANSFER (Ref# 328012838897) 7,465.00 Cr
29/03/2023 BHAVNA CHEMIST 848.00
29/03/2023 ANUPAM STATIONERY MUMBAI 199.00
04/04/2023 SpayBBPS 2100001818 Mahan 30933624 1,134.00

Первый столбец — дата, последний (в некоторых случаях предпоследний) столбец — сумма. Средняя часть "описание"

28/03/2023 | NETBANKING TRANSFER (Ref# 328012838897) | 7,465.00  | Cr
29/03/2023 | BHAVNA CHEMIST  |  848.00  | 
29/03/2023 | ANUPAM STATIONERY MUMBAI | 199.00  | 
04/04/2023 | SpayBBPS 2100001818 Mahan 30933624 | 1,134.00  | 

Есть ли способ экспортировать его в csv?

Я попробовал эту команду:

awk '{print $1 " | some magic | "  $NF}' test.txt

Как заменить «какую-то магию» на настоящий код? Я в порядке, если в последнем столбце появляется «Cr», я могу изменить это вручную.

Я могу получить второй столбец, используя cut следующим образом...

cat test.txt | cut -d ' ' -f2- | rev | cut -d ' ' -f2- | rev

Но я не уверен, как отформатировать его с первым и последним столбцом.

С разделителем из трех символов ' | ' у вас действительно нет CSV-файла.

dawg 15.04.2023 15:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
86
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Использование sed

$ sed -E 's~[0-9/]+~& |~;s~([0-9]+,)?[0-9]+\.[0-9]+~| & |~' input_file
28/03/2023 | NETBANKING TRANSFER (Ref# 328012838897) | 7,465.00 | Cr
29/03/2023 | BHAVNA CHEMIST | 848.00 |
29/03/2023 | ANUPAM STATIONERY MUMBAI | 199.00 |
04/04/2023 | SpayBBPS 2100001818 Mahan 30933624 | 1,134.00 |

Некоторое объяснение этой магии будет оценено по достоинству.

shantanuo 15.04.2023 07:40

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

28/03/2023 NETBANKING TRANSFER (Ref# 328012838897) 7,465.00 Cr
29/03/2023 BHAVNA CHEMIST 848.00
29/03/2023 ANUPAM STATIONERY MUMBAI 199.00
04/04/2023 SpayBBPS 2100001818 Mahan 30933624 1,134.00

затем

awk '{$1=$1 " |";if ($NF+0){$NF = "| " $NF}else{$(NF-1) = "| " $(NF-1)};print}' file.txt

дает вывод

28/03/2023 | NETBANKING TRANSFER (Ref# 328012838897) | 7,465.00 Cr
29/03/2023 | BHAVNA CHEMIST | 848.00
29/03/2023 | ANUPAM STATIONERY MUMBAI | 199.00
04/04/2023 | SpayBBPS 2100001818 Mahan 30933624 | 1,134.00

Объяснение: я добавляю пробел, за которым следует символ вертикальной черты, к первому полю, чтобы отделить 1-е поле от остальных, затем я проверяю, имеет ли последний файл префикс, который представляет собой ненулевое число, если он сохраняется, я добавляю трубку, за которой следует пробел, к последнему полю, в противном случае я добавляю что поле перед последним. Отказ от ответственности Я предполагаю, что ваши входные данные всегда имеют 3 или более полей, если это не так, не используйте мой код.

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

Ваша первая строка должна отделять Cr как четвертое поле, а остальные имеют пустое поле, не так ли?

dawg 15.04.2023 15:17

Все, что связано с PCRE, разрешает этот анализ.

Регулярное выражение:

/^(\d\d/\d\d/\d\d\d\d)\s+(.*?)\s+([\d,]+\.\d\d) *(.*)$/

Разделяет четыре группы. Демо

Вот Ruby, использующий это регулярное выражение:

ruby  -e '$<.each{|line|
    puts line.scan(/^(\d\d/\d\d/\d\d\d\d)\s+(.*?)\s+([\d,]+\.\d\d) *(.*)$/).join(" | ") }
' file 

Или Перл:

perl -nE 'say join(" | ", $1, $2, $3, $4) 
           if m/^(\d\d/\d\d/\d\d\d\d)\s+(.*?)\s+([\d,]+\.\d\d) *(.*)$/' file 

Вы также можете сделать это в два этапа с помощью sed, если версия поддерживает {repetitions}, что делают большинство современных версий:

sed -E 's/^[0-9]{2}/[0-9]{2}/[0-9]{4} /&| /; s/(.*) ([0-9,]{1,}\.[0-9]{2})(.*)$/\1 | \2 | \3/' file

Любой из этих принтов:

28/03/2023 | NETBANKING TRANSFER (Ref# 328012838897) | 7,465.00 | Cr
29/03/2023 | BHAVNA CHEMIST | 848.00 | 
29/03/2023 | ANUPAM STATIONERY MUMBAI | 199.00 | 
04/04/2023 | SpayBBPS 2100001818 Mahan 30933624 | 1,134.00 | 
Ответ принят как подходящий

Это может сработать для вас (GNU sed):

sed -E 's/( .*)( [0-9,.]+) ?/ |\1 |\2 | /' file

Используя жадность: поместите 3 разделителя | (с пробелами по обеим сторонам), заменив первый пробел, тот, что перед последним числом, и после последнего числа.

элегантно и читабельно. Проголосовал и принял.

shantanuo 17.04.2023 05:21

Я получаю те же результаты, если удаляю пробел и вопросительный знак '?' Это нормально или это необходимо?

shantanuo 17.04.2023 05:46

@shantanuo просто belt n'braces на случай, если число будет самым последним полем в строке.

potong 17.04.2023 10:57

Предположения:

  • желаемый вывод всегда должен иметь 1 пробел до/после | (в отличие от примера вывода OP, который варьируется от 1 до 2 пробелов)
  • если в строке есть необязательное 4-е поле (например, Cr в примере), это 4-е поле никогда не содержит числа
  • если в строке нет необязательного 4-го поля, мы заканчиваем строку | (без пробела в конце)

Одна awk идея:

awk '
      { $1=$1 " |"                     # append " |" to 1st field
        if ($NF ~ /[0-9]/)             # if last field is a monetary value (ie, no 4th field)
           $NF = "| " $NF " |"           # prepend with "| " and end line with "|" (sans trailing white space)
        else {                         # else prepend last two fields with "| "
           $(NF-1) = "| " $(NF-1)
           $NF = "| " $NF
        }
      }
1                                      # print modified line to stdout
' test.txt

Это генерирует:

28/03/2023 | NETBANKING TRANSFER (Ref# 328012838897) | 7,465.00 | Cr
29/03/2023 | BHAVNA CHEMIST | 848.00 |
29/03/2023 | ANUPAM STATIONERY MUMBAI | 199.00 |
04/04/2023 | SpayBBPS 2100001818 Mahan 30933624 | 1,134.00 |

Предполагая, что вам действительно нужен действительный вывод CSV, используйте GNU awk в качестве третьего аргумента для match():

$ cat tst.awk
BEGIN { OFS = "\",\"" }
match($0,/^(\S+)\s+(.*\S)\s+([0-9][0-9,.]*)\s*(\S+)?$/,a) {
    print "\"" a[1], a[2], a[3], a[4] "\""
}

$ awk -f tst.awk file
"28/03/2023","NETBANKING TRANSFER (Ref# 328012838897)","7,465.00","Cr"
"29/03/2023","BHAVNA CHEMIST","848.00",""
"29/03/2023","ANUPAM STATIONERY MUMBAI","199.00",""
"04/04/2023","SpayBBPS 2100001818 Mahan 30933624","1,134.00",""

Если ваши строки ввода могут содержать двойные кавычки, добавьте их непосредственно перед строкой print, чтобы избежать их в выводе:

    for ( i=1; i in a; i++ ) {
        gsub(/"/,"\"\"",a[i])
    }

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