Разделить определенные поля CSV-файла, чтобы распределить их поверх нескольких строк, сохранив при этом значения неразделенных полей

Вы можете использовать собственные операции со строками оболочки:

TEST="test  1234 foo"
SPLIT_VAR=${TEST/ */ }

Он заменит первое совпадение с шаблоном " *" (на один пробел, а затем что угодно )и заменит его на " " (на один пробел ). Таким образом, вы сохраняете первое слово и первый пробел.

См.http://www.tldp.org/LDP/abs/html/string-manipulation.htmlдля получения дополнительной информации об использовании манипуляций со строками.

И в качестве примечания, это также работает менее развитая оболочка (, протестированная на реализации ash в busybox ).

0
28.02.2020, 16:23
4 ответа
awk -F, -v OFS=, '{split("",q);for(i=j=1;i<=NF;i++){if(split($i,a,/\$/)>1){j++;$i=a[1];q[i]=a[2]}}print;if(j>1){for(i in q)$i=q[i];print}}' file

Или, расширенный:

awk -F, -v OFS=, '{
  split("", q)       # clear the q array; delete q is non-standard
  for(i = j = 1; i <= NF; i++){
    if(split($i, a, /\$/) > 1){  # if the field contains a $
       j++                # increase the cnt of fields with a $
       $i = a[1]          # set the field to the part before the $
       q[i] = a[2]        # save the part after the $ in the q array
    }
  }
  print                   # print the line with the parts before $
  if(j > 1){              # if any field had a $
     for(i in q)          # for each field which had a $
       $i = q[i]          # replace it with the part after $  
     print                # re-print the line with the parts after $
  }
}' file
0
28.04.2021, 23:21
$ perl -F, -lane '$,=",";
    print,next unless /\$/;
    for(@F) {
      my @e = split /\$/;
      push @A, @e ? $e[0] : $_;
      push @B, @e ? $e[1] : $_;
    }
    print splice @$_ for \(@A, @B);
'  file.csv

краткая работа:

только строки, в которых есть литерал $, мы перебираем поля и разбиваем поле на два, в которых есть $.

Затем заполните два массива A и B

Наконец, распечатайте и очистите массивы AB для следующей записи.

0
28.04.2021, 23:21

Если я правильно понимаю, что некоторые поля являются «двойными» полями вариантов, разделенными $, и вам просто нужны две копии этих строк, первая строка которых содержит первый вариант, а вторая строка — второй вариант...

awk '{v1=$0; gsub(/\$[^,]+/,""); gsub (/,[^,]+\$/,",",v1); print $0; if (v1!=$0) print v1}' file1

IMSI,MSISDN,SUBCATEGY,EPCMMEHOST,EPCMMEREALM,EPCROAMSCH,PSROAMSCH,OINR,MSCNUMBER,VLRNUMBER,SGSNNUMBER,EPCAPNNAME,EPCAPNAMBRUP,EPCAPNAMBRDOWN,EPCAMBRUP,EPCAMBRDOWN,CHARGE,EPCCHARGCHRT
NAN,NAN,2,,,0,,0,,,,OLAP,200000000,400000000,200000000,400000000,5,5
NAN,NAN,2,,,0,,0,,,,DOLAP,2048000,2048000,200000000,400000000,5,5
0
28.04.2021, 23:21

Я предполагаю, что точка, упомянутая @Paul _Pedant, действительно была опечаткой, и поле OLAP$DOLAPтакже должно быть разделено. В этом случае может работать следующая awkпрограмма (назовем ееsplitfields.awk):

#/usr/bin/awk -f
{
    copy=0;

    for (i=1;i<=NF;i++)
    {
        j=index($i,"$");
        if (j>0)
        {
            fields[i]=substr($i,j+1);
            $i=substr($i,1,j-1);
            copy=1
        }
        else fields[i]=$i;
    }
    print;

    if (copy==1)
    {
        for (i=1;i<NF;i++) printf("%s%s",fields[i],OFS);
        printf("%s%s",fields[NF],ORS)
    }
}

Вы можете использовать его, позвонив по телефону

user@host~$ awk -F, -v OFS="," -f splitfields.awk input.csv

Сценарий проверяет каждое поле на наличие знака $и создает копию этого поля в массиве fieldsдля возможного дальнейшего использования. Если $найдено,соответствующее поле текущей строки сокращается до части до до $, а соответствующая запись в массиве fieldsзаполняется частью после $.

После этой проверки в любом случае печатается (возможно измененная )текущая строка. Кроме того, если какое-либо из полей содержало знак $, новая строка, состоящая из содержимого массива fields, печатается в формате CSV.

0
28.04.2021, 23:21

Теги

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