Как добавить столбец n из всех файлов csv и сохранить в другом файле csv (с заголовком, являющимся именем файла, из которого взят столбец)?

#csv #awk #header

#csv #awk #заголовок

Вопрос:

У меня есть несколько файлов .csv, и я хочу извлечь определенный столбец из каждого. Допустим, столбец 5. Я хочу взять этот столбец и добавить его в файл csv и добавить к нему новый столбец из каждого последующего файла. Я могу сделать это с помощью следующего кода, взятого у кого-то другого:

 awk '{_[FNR]=(_[FNR] OFS $1)}END{for (i=1; i<=FNR; i  ) {sub(/^ /,"",_[i]); print _[i]}}' input*.csv > output.csv`
 

Когда я смотрю на выходной файл, я замечаю, что порядок, в котором добавляются столбцы, не является последовательным. В результате я надеялся изменить код так, чтобы заголовок столбца был именем файла, из которого был получен столбец. Как я могу это сделать?

Например: input1.csv может быть:

 1,2,3,4,5
6,7,8,9,10
 

input2.csv может быть:

 11,12,13,14,15
16,17,18,19,20
 

И я бы хотел, чтобы output.csv был:

 input1.csv, input2.csv
5,15
10,20
 

Я надеюсь, что это имеет смысл и заранее благодарен.

Комментарии:

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

2. Я отредактировал вопрос — спасибо!

3. Не называйте переменную _ — это еще хуже для удобства чтения кода, чем использование опаленной буквы.

4. Спасибо @EdMorton — как я уже упоминал, я получил этот код от кого-то другого и имею ограниченные знания о awk. Итак, я не уверен на 100%, что такое переменная _? Я знаю, что вы не должны слепо использовать код, и я приложу больше усилий, чтобы понять, что на самом деле происходит. Спасибо за совет, хотя!

5. Пожалуйста. _[FNR] это массив с именем _ , индексируемым значением переменной FNR . Почти любое другое имя было бы лучшим — даже a[] лучше, чем _[] потому, что, по крайней мере, тогда вы сразу понимаете, что это просто массив.

Ответ №1:

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

 awk '
BEGIN{ FS=OFS="," }
FNR==1{
  fileName=(fileName?fileName", ":"")FILENAME
}
{
  max=(max>FNR?max:FNR)
  val[FNR]=(val[FNR] == "" ? "" : val[FNR] OFS) $NF
}
END{
  print fileName
  for(i=1;i<=max;i  ){
    print val[i]
  }
}
' *.csv  > output.csv
 

С показанными примерами выходной файл с именем output.csv будет упакован со следующим содержимым.

 input1.csv, input2.csv
5,15
10,20
 

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

 awk '                                           ##Starting awk program from here.
BEGIN{ FS=OFS="," }                             ##Starting BEGIN section from here and setting field separator and output field separator as comma here.
FNR==1{                                         ##If this is first line of all Input_file
  fileName=(fileName?fileName", ":"")FILENAME   ##Creating fileName which has current Input_file name in it and keep adding it.
}
{
  max=(max>FNR?max:FNR)                         ##Creating max, to get highest number of lines.
  val[FNR]=(val[FNR] == "" ? "" : val[FNR] OFS) $NF        ##Creating val with index of FNR and keep adding values of last field in it.
}
END{                                            ##Starting END block of this program from here.
  print fileName                                ##Printing all file names in outputFile.
  for(i=1;i<=max;i  ){                          ##Starting for loop from 1 to max here.
    print val[i]                                ##Printing array val value here.
  }
}
' *.csv > output.csv                            ##Mentioning all *.csv files here.
 

Комментарии:

1. Спасибо @RavinderSingh13 Я только что попробовал, но он не печатал только один столбец из каждого файла. Он печатал все из каждого файла. Он напечатал заголовок с файлами, разделенными пробелом «filename1, ,filename2, , filename3 ……».

2. @BenWest, не могли бы вы попробовать мое отредактированное решение? просто обновите эту страницу один раз и запустите последнее решение, дайте мне знать, как это происходит, у меня все получилось, дайте мне знать.

3. Отлично, моя ошибка, я понял, что мои файлы csv на самом деле не имеют правильного разделителя. Если бы я хотел изменить, какой столбец нуждается в печати, как бы я это сделал? Скажем, я хотел напечатать столбец 3 входных файлов, а не 5?

4. @BenWest, приветствую вас. В случае изменения номера столбца измените с $NF на $3 (где $ NF — последнее поле строки), приветствия и счастливого обучения.

5. Неважно — я понял это! Спасибо за всю помощь!