Как заменить каждое вхождение в CSV-файле, кроме одного столбца. awk csv bash mac - PullRequest
0 голосов
/ 27 января 2020

как мне изменить этот awk-скрипт? Он изменяет каждое вхождение, но должно изменять каждое вхождение, кроме одного столбца. Большая проблема в том, что указанный столбец c не всегда является первым. Но я знаю имя столбца в заголовке.

awk '
BEGIN{
  FS=OFS=","
}
FNR==1{
  print
  next
}
{
  for(i=1;i<=NF;i++){
    sub(/^\/Text[0-9]+Text/,"",$i)
    sub(/Text.*/,"",$i)
  }
}
1
'  Input_file

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

awk '
BEGIN{                                 ##Starting BEGIN section of code here.
  FS=OFS=","                           ##Setting FS and OFS to comma here.
}
FNR==1{                                ##Checking condition if FNR==1 then do following.
  print                                ##Printing the current line here.
  next                                 ##next will skip all further statements from here.
}
{
  for(i=1;i<=NF;i++){                  ##Starting a for loop to traverse into all fields here.
    sub(/^\/Text[0-9]+Text/,"",$i)     ##Substituting from starting Text digits Text with NULL in current field.
    sub(/Text.*/,"",$i)                ##Substituting everything from Text to till last of field value with NULL in current field.
  }
}
1                                      ##1 will print edited/non-edited line here.
'  Input_file                          ##Mentioning Input_file name here.

Пример файла:

header1, header2, header3-dont-modify-this-column, header4, header5
,,/Text2234Text7846641Text.html,/Text2234Text7846641Text.html,/Text2234Text823241Text.html
,,/Text2234Text7846642Text.html,/Text2234Text7846642Text.html,/Text2234Text823242Text.html
,,/Text2234Text7846643Text.html,/Text2234Text7846643Text.html,/Text2234Text823243Text.html

Результат должен быть:

header1, header2, header3-dont-modify-this-column, header4, header5
,,/Text2234Text7846641Text.html,7846641,823241
,,/Text2234Text7846642Text.html,7846642,823242
,,/Text2234Text7846643Text.html,7846643,823243

Спасибо

Ответы [ 2 ]

2 голосов
/ 27 января 2020

Можно написать версию code-golf , чтобы выполнить именно то действие, которое вам требуется. Тем не менее, я напишу что-то более общее c, которое легче поддерживать. Идея состоит в том, чтобы отслеживать порядок заголовков в массиве h. Пример h[2] содержит значение заголовка второго столбца. Кроме того, мы будем использовать ассоциативный массив v, который индексируется по значению заголовка. Изменяя значения массива v, вы можете восстановить CSV на основе v[h[i]].

. Мы устанавливаем разделитель полей равным . Если запятые могут быть частью поля из-за кавычек, взгляните на: Какой самый надежный способ эффективного анализа CSV с помощью awk?

awk 'BEGIN{FS=OFS=","}
     (FNR==1) { for(i=1;i<=NF;++i) h[i]=$i; print; next }
     { for(i=1;i<=NF;++i) v[h[i]]=$i }
     { #perform modifications here based on v["header_name"]="new val" }
     { for(i=1;i<=NF;++i) printf v[h[i]] (i==NF?ORS:OFS) }' file

Пример: Я хочу изменить столбцы с заголовками "h2" и "h3", дать им значение 0

Ввод:

h3,h1,h2,h4
1,2,3,4
5,6,7,8

Используется AWK:

awk 'BEGIN{FS=OFS=","}
     (FNR==1) { for(i=1;i<=NF;++i) h[i]=$i; print; next }
     { for(i=1;i<=NF;++i) v[h[i]]=$i }
     {  v["h2"]=v["h3"]=0 }
     { for(i=1;i<=NF;++i) printf v[h[i]] (i==NF?ORS:OFS) }' file

Выход:

h3,h1,h2,h4
0,2,0,4
0,6,0,8
1 голос
/ 27 января 2020

Не могли бы вы попробовать следующее. В соответствии с показанным примером вывода OP не хочет подменять 3-е поле, поэтому я пренебрег им.

awk '
BEGIN{
  FS=OFS=","
}
FNR==1{
  print
  next
}
{
  for(i=1;i<=NF;i++){
    if(i!=3){
      sub(/^\/Text[0-9]+Text/,"",$i)
      sub(/Text.*/,"",$i)
    }
  }
}
1
'  Input_file


ИЛИ используйте подход с переменными, при котором создается переменная для кода awk и упомяните номер поля там, который вы хотите игнорировать для подстановки.

awk -v ignore_field="3" '
BEGIN{
  FS=OFS=","
}
FNR==1{
  print
  next
}
{
  for(i=1;i<=NF;i++){
    if(i!=ignore_field){
      sub(/^\/Text[0-9]+Text/,"",$i)
      sub(/Text.*/,"",$i)
    }
  }
}
1
'  Input_file

Добавление подробного объяснения приведенного выше кода здесь:

awk -v ignore_field="3" '                  ##Starting awk program and mentioning variable name ignore_field as 3, which will have value field to be ignored.
BEGIN{                                     ##Starting BEGIN section from here.
  FS=OFS=","                               ##Setting FS and OFS comma here.
}
FNR==1{                                    ##Checking condition if line is first line then do following.
  print                                    ##Printing current line here.
  next                                     ##next will skip all further statements from here.
}
{
  for(i=1;i<=NF;i++){                      ##Starting a for loop which starts from i=1 to till value of NF in current line.
    if(i!=ignore_field){                   ##Checking condition if current field is NOT equal to variable ignore_field then do following.
      sub(/^\/Text[0-9]+Text/,"",$i)       ##Substituting starting Text digits then Text string with NULL in current field.
      sub(/Text.*/,"",$i)                  ##Substituting string Text till end with NULL in current field.
    }
  }
}
1                                          ##Mentioning 1 will print edited/non-edited line.
' Input_file                               ##Mentioning Input_file name here.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...