Разделить и обработать текстовый файл в sh - PullRequest
0 голосов
/ 14 марта 2019

У меня есть текстовый файл с разделителем-запятой (,):

60,tel:+33xxxxxxx,840191,1,0,tel:+33xxxxxxx;kn-corp-groups=3_6,8401
61,tel:+33xxxxxxx,840191,1,1,tel:+33xxxxxxx;kn-corp-groups=4_60,8401
60,tel:+33xxxxxxx,840191,1,0,tel:+33xxxxxxx;kn-corp-groups=3_5,8401
61,tel:+33xxxxxxx,840191,1,1,tel:+33xxxxxxx;kn-corp-groups=1_59,8401

Я хотел бы получить вывод:

60,tel:+33xxxxxxx,840191,1,0,3,6,8401
61,tel:+33xxxxxxx,840191,1,1,4,60,8401
60,tel:+33xxxxxxx,840191,1,0,3,5,8401
61,tel:+33xxxxxxx,840191,1,1,1,59,8401

Таким образом, для каждой строки я сплющил поле "tel: + 33xxxxxxx; kn-corp-groups = 3_6" в "3,6", например.

Не могли бы вы представить, как я могу это сделать? Спасибо

Ответы [ 7 ]

3 голосов
/ 14 марта 2019

Для этих данных:

$ awk 'BEGIN{FS="[,_=]";OFS=","}{print $1,$2,$3,$4,$5,$7,$8,$9}' file

Выход:

60,tel:+33xxxxxxx,840191,1,0,3,6,8401
61,tel:+33xxxxxxx,840191,1,1,4,60,8401
60,tel:+33xxxxxxx,840191,1,0,3,5,8401
61,tel:+33xxxxxxx,840191,1,1,1,59,8401

Разъяснения:

$ awk 'BEGIN{
    FS="[,_=]"                    # use multiple chars as field separators
    OFS=","
}
{
    print $1,$2,$3,$4,$5,$7,$8,$9
}' file
0 голосов
/ 15 марта 2019
awk '{sub(/_/,",")}{print (substr($0, 1,29) substr($0, 60))}' file

60,tel:+33xxxxxxx,840191,1,0,3,6,8401
61,tel:+33xxxxxxx,840191,1,1,4,60,8401
60,tel:+33xxxxxxx,840191,1,0,3,5,8401
61,tel:+33xxxxxxx,840191,1,1,1,59,8401
0 голосов
/ 14 марта 2019

Использование регулярных выражений Perl

perl -pe ' s/(.*)(tel:.*=)(.*)_(.*)/$1$3,$4/ ' file

с заданными вами значениями

$ cat shakile.txt
60,tel:+33xxxxxxx,840191,1,0,tel:+33xxxxxxx;kn-corp-groups=3_6,8401
61,tel:+33xxxxxxx,840191,1,1,tel:+33xxxxxxx;kn-corp-groups=4_60,8401
60,tel:+33xxxxxxx,840191,1,0,tel:+33xxxxxxx;kn-corp-groups=3_5,8401
61,tel:+33xxxxxxx,840191,1,1,tel:+33xxxxxxx;kn-corp-groups=1_59,8401

$ perl -pe ' s/(.*)(tel:.*=)(.*)_(.*)/$1$3,$4/ ' shakile.txt
60,tel:+33xxxxxxx,840191,1,0,3,6,8401
61,tel:+33xxxxxxx,840191,1,1,4,60,8401
60,tel:+33xxxxxxx,840191,1,0,3,5,8401
61,tel:+33xxxxxxx,840191,1,1,1,59,8401

$
0 голосов
/ 14 марта 2019

sed

awk уже был охвачен другими ответами.Вот альтернативный вариант использования sed :

$ sed -E -e 's/[^,]+;[^=]+=//' -e 's/_/,/' file

Пояснение

  • sed -E для использования Расширенной регулярнойвыражения .
  • sed -e выполняет сценарий sed.Не забудьте заключить сценарии sed в одинарные кавычки ('), чтобы не допустить расширения оболочки.Нам нужно будет выполнить два сценария.

  • s/[^,]+;[^=]+=// Первый из двух сценариев.Удаляет ненужную нам строку ( тел: + 33xxxxxxx; группы kn-corp = ):

    • Замена (s/)
    • один или несколько символов, не являющихся запятой ([^,]+)
    • , за которыми следует одна точка с запятой (;)
    • , за которой следует один или несколько символов, не являющихся знаком равенства ([^=]+)
    • , за которым следует один знак равенства (=)
    • без нуля, т. Е. Удаляется соответствующая строка (//).
  • s/_/,/ Второй из двух сценариев.Заменяет подчеркивание (_) между двумя числами запятой (,):
    • Подставка (s/)
    • одиночное подчеркивание (_)
    • с запятой (/,/).

Альтернативы

Еще несколько вариантов оболочки без awk:

  • sed трубопровод
    Два сценария sed могли бы также использоваться с каналом:
    $ sed -E 's/[^,]+;[^=]+=//' file | sed 's/_/,/'.
    Это было бы менее эффективно, но если скорость не имеет значения, некоторым людям будет легче ее понять.Подробнее см. в этом ответе .
  • sed + tr
    Вторую часть вышеприведенной трубы можно заменить простой trкоманда:
    $ sed -E 's/[^,]+;[^=]+=//' file | tr '_' ','.
  • tr + cut
    Мы также можем обойтись без sed:
    $ tr '=_' ',' < file | cut -d, -f 1-5,7-9
    Здесь мысначала замените = и _ на ,, используя tr, чтобы наши поля были разделены запятыми,
    и напечатайте все поля, кроме 6-го, с cut (-dобозначает разделитель, который равен ,, а -f обозначает поля, которые мы хотим напечатать, т.е. все, кроме 6-го).
  • sed групповые субтитры
    См. Также Ответ Эда Мортона , который использует групповые субтитры.
0 голосов
/ 14 марта 2019
$ sed 's/[^,]*;[^,]*\([0-9]*\)_/\1,/' file
60,tel:+33xxxxxxx,840191,1,0,3,6,8401
61,tel:+33xxxxxxx,840191,1,1,4,60,8401
60,tel:+33xxxxxxx,840191,1,0,3,5,8401
61,tel:+33xxxxxxx,840191,1,1,1,59,8401
0 голосов
/ 14 марта 2019

use gawk:

awk 'BEGIN{ FS=OFS="," } NF {$(NF-1) = gensub(/.*=(.*)_/, "\\1,", 1, $(NF-1))}1' file

Здесь нам просто нужно обработать следующий за последним столбцом $(NF-1) с gensub() и NF в качестве условия для пропуска пустых строк.

0 голосов
/ 14 марта 2019

Не могли бы вы попробовать, если я правильно понял, вам нужно выбрать строки, в которых есть строка tel:+33xxxxxxx.

awk -F'[,_=]' 'BEGIN{OFS=","} /tel:\+33xxxxxxx/{print $1,$2,$3,$4,$5,$7,$8,$9}'  Input_file


2ndрешение: Если вы не хотите жестко кодировать (эти значения могут быть где угодно в Input_file), то номера полей затем попробуйте выполнить следующее.

awk '
BEGIN{
  OFS=","
}
match($0,/^[0-9]+\,tel:\+33xxxxxxx\,[0-9]+\,[0-9]+\,[0-9]+/){
  val=substr($0,RSTART,RLENGTH)
  match($0,/kn-corp-groups=[0-9]+_[0-9]+\,[0-9]+/)
  val1=substr($0,RSTART+15,RLENGTH-15)
  sub("_",",",val1)
  print val,val1
  val=val1=""
}'   Input_file

Вывод будет следующим.

60,tel:+33xxxxxxx,840191,1,0,3,6,8401
61,tel:+33xxxxxxx,840191,1,1,4,60,8401
60,tel:+33xxxxxxx,840191,1,0,3,5,8401
61,tel:+33xxxxxxx,840191,1,1,1,59,8401
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...