#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. Неважно — я понял это! Спасибо за всю помощь!