Какую команду grep / awk / sed использовать для вывода, который я хочу - PullRequest
0 голосов
/ 06 марта 2019

У меня есть такой файл ввода:

COL1: VALUE1 , XYZ: 2, OWNER: (DSF) , FLG: DIT /-/-/ OX if 0X, proc=0xyyy23, NAME=AUDIT
COL1: VALUE2 , XYZ: 2, OWNER: (DSF) , FLG: DIT /-/-/ OX if 0X, proc=0xyy23, NAME=generic
XYZ:2, COL1: 289 , TREK:MRP, OWNER: (DSF) , FLG: DIT /-/-/ OX if 0X,  NAME=Oil, trial=TREE

Я хочу получить вывод, подобный этому:

  COL1: VALUE1 , NAME=AUDIT
  COL1: VALUE2 , NAME=generic
  COL1: 289    , NAME=Oil

Как мне добиться этого, используя awk/grep/sed в командной строкебез использования каких-либо расширенных версий awk, таких как gawk, nawk и т. д.?

Обычно я хочу получить значение COL1 (т. Е. Текст после : и =) & NAME независимо от того, где они находятся в строке.
См. Это местоположение NAMEколонка немного изменилась.

Вот что я могу придумать:

awk -F"," '{print $1, $6}' file.txt
COL1: VALUE1   NAME=AUDIT
COL1: VALUE2   NAME=generic
XYZ:2   NAME=Oil

Ответы [ 5 ]

4 голосов
/ 06 марта 2019

Вы можете попробовать Perl однострочное

 perl -lne ' /(COL1:\s*\S+).+(NAME=\w+)/ and print "$1,\t$2" ' input_file

со своими вводами:

$ cat sach.txt
COL1: VALUE1 , XYZ: 2, OWNER: (DSF) , FLG: DIT /-/-/ OX if 0X, proc=0xyyy23, NAME=AUDIT
COL1: VALUE2 , XYZ: 2, OWNER: (DSF) , FLG: DIT /-/-/ OX if 0X, proc=0xyy23, NAME=generic
XYZ:2, COL1: 289 , TREK:MRP, OWNER: (DSF) , FLG: DIT /-/-/ OX if 0X,  NAME=Oil, trial=TREE
$ perl -lne ' /(COL1:\s*\S+).+(NAME=\w+)/ and print "$1,\t$2" ' sach.txt
COL1: VALUE1,   NAME=AUDIT
COL1: VALUE2,   NAME=generic
COL1: 289,      NAME=Oil
$

Объяснение:

perl -lne  # use -n for suppressing print default at the end of each line

' /(COL1:\s*\S+).+(NAME=\w+)/  # Match pattern and capture them in capture groups first () will be $1 and second () will be in $2
                               # First ()  matches COL1:\s*\S+ => COL1: followed by zero or more spaces using \s* and \S+ for non-space characters
                               # .+ => match all strings between first () and second ()
                               # Seecond ()  matches NAME followed by a word \w+


and                            # bind on the success of previous condition /..../
print "$1,\t$2"                # print the $1 and $2 captured variables 

' input_file
1 голос
/ 06 марта 2019

Не могли бы вы попробовать следующее (протестировано и написано в GNU awk).

awk '
BEGIN{
  OFS=" , "
}
match($0,/COL[0-9]+: [^,]*/){
  val=substr($0,RSTART,RLENGTH)
  match($0,/NAME[^,]*/)
  print val OFS substr($0,RSTART,RLENGTH)
  val=""
}
'   Input_file

Я забил совпадение (я) строки COL и NAME в каждой строке, поэтому, если в строке нет строки COL, она может ничего не печатать.



В случае, если строка COL не найдена в строке, и вы все еще хотите напечатать NAME соответствие строки, попробуйте выполнить следующее.

awk '
BEGIN{
  OFS=" , "
}
match($0,/COL[0-9]+: [^,]*/){
  val=substr($0,RSTART,RLENGTH)
}
match($0,/NAME[^,]*/){
  if(val){
    printf "%s%s",val,OFS
  }
  print substr($0,RSTART,RLENGTH)
}
'    Input_file


Объяснение: Добавление пояснения к вышеприведенному коду.

awk '                                          ##Starting awk program heer.
BEGIN{                                         ##Starting BEGIN section for awk code here.
  OFS=" , "                                    ##Setting OFS output field separator as space comma space here.
}                                              ##Closing BEGIN section here.
match($0,/COL[0-9]+: [^,]*/){                  ##Using match of awk OOTB function to match a REGEX string COL till comma here.
  val=substr($0,RSTART,RLENGTH)                ##If a match is foundthen creating variable val whose value is sub string of matched regex starting to till end value of it.
  match($0,/NAME[^,]*/)                        ##Again using match to match string from NAME to till next comma comes.
  print val OFS substr($0,RSTART,RLENGTH)      ##Printing value of variable val OFS and substring of current line whose sarting point is RSTART and end point is RLENGTH.
  val=""                                       ##Nullifying variable val here.
}
'  Input_file                                  ##Mentioning Input_file name here.

Добавление ссылки со страницы man awk:

   RSTART      The index of the first character matched by match(); 0 if no match.  (This implies that character indices start at one.)

   RLENGTH     The length of the string matched by match(); -1 if no match.
0 голосов
/ 07 апреля 2019

от GNU SED

$ sed -E 's/^([^,]+,\s*)?(col1:[^,]+).+(,\s*name=\w+).*/\2\3/i' file.txt
0 голосов
/ 06 марта 2019

Попробуйте это:

$ sed 'H;s/.*NAME=/NAME=/;s/ *,.*//;x;s/^.*COL1/COL1/;s/ *,.*//;G;s/\n/\t, /;' file
COL1: VALUE1    , NAME=AUDIT
COL1: VALUE2    , NAME=generic
COL1: 289       , NAME=Oil

Используется удерживающее пространство и \t используется для выравнивания.

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

С помощью grep вы можете попробовать что-то вроде этого:

while read line; do COL=$(echo $line | grep -o "COL1:.*,"); NAME=$(echo $line | grep -o "NAME=[a-zA-Z]*"); echo $COL $NAME >> new_file.txt; done < your_file.txt 

В этом примере регулярное выражение предполагает, что значение после COL1 всегда сопровождается "," (тогда оно принимает все символы между:и,) так что вам, возможно, придется адаптировать его под свой файл (то же самое для регулярного выражения, используемого для NAME).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...