Я пытался реализовать функцию в моем сценарии оболочки, но каким-то образом застрял в реализации, пожалуйста, помогите.

Sample File - f1.txt

col1|col2|col3|rev|spt
A1|54|tyre|56.89|45.23
B1|54|pole|11.89|85.23
C1|54|ture|112.89|185.23

Файлы могут иметь любое количество столбцов, и это не фиксировано. Чего я хочу добиться, так это ->

Concatenate all the Columns in the File (Note- It can have any number of Columns) except the Columns- rev and spt

Whenever it Finds Column Name as rev or spot it shouldnot include in Concatenation.
Example-

Output-
KeyCol|rev|spot
A1~54~tyre|56.89|45.23
B1~54~pole|11.89|85.23
C1~54~ture|112.89|185.23

Поэтому в идеале я хочу создать Composite в любом файле с любым количеством столбцов, кроме столбцов с именами rev и spot.

Пожалуйста помоги

0
Samrat Saha 27 Дек 2021 в 10:40
Должно быть в соответствии с именем столбца? Эти столбцы могут появляться в любом месте таблицы, не обязательно как последние два поля?
 – 
aviro
27 Дек 2021 в 11:25
Столбцы rev и spt всегда будут в последних 2 полях, это точно, но кроме этого остальные столбцы могут быть любым количеством столбцов, которые я должен создать составной ключ
 – 
Samrat Saha
27 Дек 2021 в 11:38
Имена столбцов rev и spt никогда не изменятся, но ДРУГИЕ имена столбцов могут отличаться в разных файлах @aviro
 – 
Samrat Saha
27 Дек 2021 в 11:39

1 ответ

Лучший ответ

Вот команда awk, которую вы можете использовать:

awk -F'|' 'NR==1 {OFS=FS; print "KeyCol", $(NF-1), $NF} NR > 1 {OFS="~"; LAST=$(NF-1) FS $NF; NF-=2; print $0 FS LAST}'

Объяснение

  • -F '|' означает, что разделителем полей ввода является |.
  • NR==1 означает, что работает только первая строка. В первой строке напечатайте только «KeyCol» для первого поля, а затем для двух последних полей, а OFS (разделитель выходных полей) будет FS (разделитель входных полей), что в вашем случае |.
  • На следующей следующей строке после первой (NR > 1): <ул>
  • OFS="~" означает, что новым разделителем полей вывода будет ~.
  • LAST=$(NF-1) FS $NF – сохраните два последних поля в строковой переменной с именем LAST и разделите их FS (разделитель входных полей).
  • NF-=2 – уменьшите количество полей (NF) на 2, чтобы исключить последние два поля.
  • print $0 FS LAST <ул>
  • $0 теперь содержит только первые (NF-2) поля.
  • Они будут напечатаны через OFS (в данном случае ~
  • За ним следует исходный FS (то есть |)
  • И переменная LAST, которая содержит последние два поля.

Выход

awk -F'|' 'NR==1 {OFS=FS; print "KeyCol", $(NF-1), $NF} NR > 1 {OFS="~"; LAST=$(NF-1) FS $NF; NF-=2; print $0 FS LAST}' f1.txt
KeyCol|rev|spt
A1~54~tyre|56.89|45.23
B1~54~pole|11.89|85.23
C1~54~ture|112.89|185.23

Примечание 1

Вы можете переместить строку OFS="~" в конец строки NR==1, потому что тогда она будет применяться ко всем следующим записям, и вам не нужно будет устанавливать ее для каждой строки.

awk -F'|' 'NR==1 {OFS=FS; print "KeyCol", $(NF-1), $NF; OFS="~"} NR > 1 {LAST=$(NF-1) FS $NF; NF-=2; print $0 FS LAST}'

Заметка 2

Вы можете создать awk-скрипт для его автоматизации.

$ cat composite.awk
BEGIN { FS = "|" }
NR == 1 {
  OFS=FS
  print "KeyCol", $(NF-1), $NF
  OFS="~"
} 
NR > 1 {
  LAST=$(NF-1) FS $NF
  NF-=2
  print $0 FS LAST
}

Обратите внимание, что я добавил раздел BEGIN, в котором задал FS, поэтому вам не понадобятся аргументы -F '|' для команды awk.

А затем запустите его, используя файл сценария.

$ awk -f composite.awk f1.txt                                                                                            
KeyCol|rev|spt
A1~54~tyre|56.89|45.23
B1~54~pole|11.89|85.23
C1~54~ture|112.89|185.23
1
aviro 27 Дек 2021 в 13:39