Bash команда / скрипт для разбиения строки на определенный символ - PullRequest
1 голос
/ 19 февраля 2020

Я хотел бы разделить приведенные ниже данные на ожидаемый результат:

Необработанные данные:

931096|376601|1|ART|AT-2151780724|2151780724|2|102809198|I|CGM44I|MIL3VF03|52576377.3600|PENDING|MO|PEND-INFO|Pend ACS4R|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|52576377.3600|1317720|system|2020-02-13 02:00:42|0
931097|375789|1|AYT|AT-2151509210|2151509210|7|102614605|A|CTHGMI|OZF19|444006.6400|APPROVED|NULL|APPROVED|Approved|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|kg17718|NULL|NULL|0.0000|1317722|system|2020-02-13 02:00:43|0931098|375979|1|AHT|AT-2151780726|2151780726|2|102809199|I|CGMI|MILaesLF11|26312.0000|PENDING|MO|PEND-INFO|Pend ACRES|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|26312.0000|1317721|system|2020-02-13 02:00:43|0
931099|376572|1|AT|AT-2151399812|2151399812|5|102673999|I|CG2rMI|WEL44LF15|60991.6956|PENDING|MO|PEND-INFO|Pend ACERS|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|0.0000|1317723|system|2020-02-13 02:00:45|0

Ожидаемый результат:

931096|376601|1|ART|AT-2151780724|2151780724|2|102809198|I|CGM44I|MIL3VF03|52576377.3600|PENDING|MO|PEND-INFO|Pend ACS4R|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|52576377.3600|1317720|system|2020-02-13 02:00:42|0
931097|375789|1|AYT|AT-2151509210|2151509210|7|102614605|A|CTHGMI|OZF19|444006.6400|APPROVED|NULL|APPROVED|Approved|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|kg17718|NULL|NULL|0.0000|1317722|system|2020-02-13 02:00:43|0
931098|375979|1|AHT|AT-2151780726|2151780726|2|102809199|I|CGMI|MILaesLF11|26312.0000|PENDING|MO|PEND-INFO|Pend ACRES|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|26312.0000|1317721|system|2020-02-13 02:00:43|0
931099|376572|1|AT|AT-2151399812|2151399812|5|102673999|I|CG2rMI|WEL44LF15|60991.6956|PENDING|MO|PEND-INFO|Pend ACERS|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|0.0000|1317723|system|2020-02-13 02:00:45|0

В основном \ n персонаж теряется иногда в данных, а строки объединяются. Иногда объединяется более 1 строки (даже происходит обратное, но мы можем вернуться к этому позже).

Данные всегда имеют 43 столбца | разделены. Последний столбец (42-й) всегда является меткой времени, а последний столбец обычно равен 0 или 1.

Попытка использовать следующий подход: Если столбцы> 43 Разделить 44-й столбец, чтобы добавить \ n, и вывести оставшиеся. Повторите процесс, пока столбцы = 43

echo "${curr}" | awk -F\| ' { if(NF > 43) {for(i=43;i<NF;i++) "sed '${NR}s/\(^0\)/\1\n/p' $i" }}' filename

Ответы [ 5 ]

2 голосов
/ 19 февраля 2020

Обычный способ с sed: напишите регулярное выражение, соответствующее 43 | символы с чем-либо между и ди git. Затем вставьте новую строку после совпавшей строки.

sed 's/[0-9]\{6\}\(|[^|]*\)\{41\}|[0-9]/&\n/g ; s/\n$//'
#                                               ^^^^^^^ - remove the leftover newline
#                                       ^ - the matched string
#                                 ^^^^^ - trailing digit
#                                ^ - 42th pipe character
#                ^^^^^^^^^^^^^^^^ - 41 fields with anything in between
#      ^^^^^^^^^^ - leading 6 digits

проверено на repl

Или, возможно, сопоставьте 42 канала с чем-либо впереди и с ди git ::

sed 's/\([^|]*|\)\{42\}[0-9]/&\n/g ; s/\n$//'

Или сопоставьте символ после 42 каналов и ди git и вставьте новую строку между:

sed 's/\(\([^|]*|\)\{42\}[0-9]\)\(.\)/\1\n\3/g'
2 голосов
/ 19 февраля 2020

менее сложный

awk 'BEGIN {FS=OFS="|"} 
     NF>43 {for(i=43;i<=NF;i+=42) {t=$i; $i=substr(t,1,1) ORS substr(t,2)}}1' file

931096|376601|1|ART|AT-2151780724|2151780724|2|102809198|I|CGM44I|MIL3VF03|52576377.3600|PENDING|MO|PEND-INFO|Pend ACS4R|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|52576377.3600|1317720|system|2020-02-13 02:00:42|0
931097|375789|1|AYT|AT-2151509210|2151509210|7|102614605|A|CTHGMI|OZF19|444006.6400|APPROVED|NULL|APPROVED|Approved|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|kg17718|NULL|NULL|0.0000|1317722|system|2020-02-13 02:00:43|0
931098|375979|1|AHT|AT-2151780726|2151780726|2|102809199|I|CGMI|MILaesLF11|26312.0000|PENDING|MO|PEND-INFO|Pend ACRES|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|26312.0000|1317721|system|2020-02-13 02:00:43|0
931099|376572|1|AT|AT-2151399812|2151399812|5|102673999|I|CG2rMI|WEL44LF15|60991.6956|PENDING|MO|PEND-INFO|Pend ACERS|N|N|N|N|N|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|N|NULL|NULL|N|system|NULL|NULL|0.0000|1317723|system|2020-02-13 02:00:45|0

после вашего задания c

Если столбцы> 43 Разделить 44-й 43-й столбец, чтобы добавить \ n и распечатать осталось. Повторяйте процесс, пока cols = 43 конец.

1 голос
/ 19 февраля 2020

Не могли бы вы попробовать, написано и протестировано с показанными образцами. Это решение позаботится о вставке новых строк, даже если у вас есть более 1 вхождений в одной строке.

awk '
match($0,/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\|0/){
  val=substr($0,RSTART+RLENGTH)
  if(val){
    num=gsub(/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\|0/,"&")
    while(++count<num){
      sub(/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\|0/,"&\n")
    }
  }
  val=count=num=""
}
1
'  Input_file
0 голосов
/ 20 февраля 2020

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

sed 's/[^|]*/\n&/44;s/\(|.\)\([^|]*|\)\n/\1\n\2/;P;D' file

Если есть 44-е поле, вставьте перед ним новую строку. Затем удалите эту новую строку и вставьте ее после первого символа 43-го поля. Напечатайте первую строку, удалите первую строку и повторите.

0 голосов
/ 19 февраля 2020

Вы не доверяете источнику данных. Может быть, это добавит еще один |, а количество столбцов будет неправильным.
Другой подход состоит в предположении, что вы можете доверять полю отметки времени.
Поэтому попробуйте разбить строку, когда поле после отметки времени имеет больше значения, чем дано. символ (и разделяется после первого).

sed -E 's/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\|.)(.)/\1\n\2/g' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...