Я новичок в Unix; ищу здесь решение моей проблемы. У меня нет кода для начала :) только проблема и необходимое решение.
Я хочу автоматизировать следующий процесс (т.е. воспроизвести функцию Vlookup в Excel):
Все сгенерированные файлы содержат ключ (номер транзакции) - могут располагаться в разных столбцах между разными документами.
edit: предположим, что экстракты не отсортированы по транзакции №.
пример, Table1:
field1,field2,field3,Transaction#,field4
ABC,ABC,ABC,1,CFG
ABC,ABC,ABC,2,CFG
ABC,ABC,ABC,3,CFG
пример, Table2:
field1;Transaction#;field3;field4;field5
ABC;1;ABC;ABC;CFG
ABC;2;ABC;ABC;CFG
ABC;3;ABC;ABC;CFG
У меня есть таблица поиска, которая выглядит следующим образом:
Transaction # New #
1 122
2 123
3 124
Мне нужно добавить столбец с заголовком New # в конце каждой таблицы csv:
edit: предположим, что не все транзакции из таблицы поиска присутствуют во входной таблице; и не все транзакции из входной таблицы присутствуют в таблице поиска.
пример, Таблица1:
field1,field2,field3,Transaction#,field4,new#
ABC,ABC,ABC,1,CFG,122
ABC,ABC,ABC,2,CFG,123
ABC,ABC,ABC,3,CFG,124
пример, Таблица2:
field1;Transaction#;field3;field4;field5;new#
ABC;1;ABC;ABC;CFG;122
ABC;2;ABC;ABC;CFG;123
ABC;3;ABC;ABC;CFG;124
Я предполагаю, что и ваши таблицы, и файл подстановки являются CSV, у них одинаковый разделитель и используются одинаковые соглашения о кавычках. Если нет, вам нужно сначала нормализовать их каким-либо другим способом.
Я также предполагаю, что файл поиска достаточно мал для чтения в памяти. Если это не так, вам, вероятно, следует преобразовать данные в SQL.
С этими предположениями вы можете использовать awk
:
awk -F , -v OFS=, -v col=4 '
NR == 1 { next }
NR == FNR {
n[$1] = $2
}
NR != FNR {
NF++
$NF = FNR == 1 ? "new" : n[$col]
print
}' lookup.csv Table1.csv
Вы можете настроить -F
, OFS
и col
выше, чтобы сопоставьте разделитель CSV и соответствующий столбец в таблице.
Я не думаю, что инструменты обработки текста справятся с этой задачей. Вместо этого я рекомендую использовать язык, должным образом оснащенный для работы с CSV-файлами.
Вот предложение на R ( http://r-project.org , довольно сложно эффективно гуглить, если вы этого не знаете).
#!/usr/bin/Rscript
args <- commandArgs(TRUE)
# Here, we read each table passed as argument on the commandline
tablenames <- list()
for (tablename in args) {
header <- readLines(tablename, n=1)
# we try to detect the separator (the character that surrounds "Transaction#")
# That doesn't work if you use multi-characters separators
sep <- sub(".*(.)Transaction#.*","\\1",header)
if (nchar(sep[1]) != 1) {
sep <- sub(".*Transaction#(.).*","\\1",header)
}
if (nchar(sep[1]) != 1) {
print(paste0("Could not detect separator around column 'Transaction#' in file ",tablename))
} else {
# each table where the separator is succesfully detected
# is added to a list of tablenames
tablenames[[tablename]] <- list(name=tablename,sep=sep)
}
}
# we parse each table in the list of tablenames
tables <- lapply(tablenames, function(tab) { read.csv(tab$name, check.names=FALSE, sep=tab$sep) })
# we also parse the lookup table, which has a different format
lookup <- read.table("lookup",header=TRUE,check.names=FALSE,comment.char="")
# then for each table, we add the new column
for (i in 1:length(tablenames)) {
# This line magic:
# - it adds a new column called "New#" to the table
# - this column is populated from table lookup
# - lines in lookup are filtered and ordered so that column "Transaction#" matches columns "Transaction#" in the table
# - we add only column "New#" from lookup to the table
tables[[i]][,"New#"] <- lookup[match(tables[[i]][,"Transaction#"],lookup[,"Transaction#"]),"New#"]
# we write back the table under the name "new <original name>"
write.table(tables[[i]], file=paste("new",tablenames[[i]]$name), sep=tablenames[[i]]$sep, quote=FALSE, row.names=FALSE)
}
Вы должны вызвать этот сценарий из каталога, в котором находятся ваши таблицы:
./script table1 table2 ...
где table1
, table2
, ... - имена файлов ваших таблиц. На момент написания сценария таблица поиска должна находиться в файле lookup
, но это можно легко изменить.
Например:
table1
field1,field2,ffield1,field2,field3,Transaction#,field4
ABC,ABC,ABC,1,CFG
ABC,ABC,ABC,3,CFG
table2
field1;Transaction#;field3;field4;field5
ABC;2;ABC;ABC;CFG
ABC;1;ABC;ABC;CFG
ABC;3;ABC;ABC;CFG
Мы запускаем ./ script.R table1 table2
.
lookup
Transaction# New#
1 122
2 123
3 124
Результаты:
новая таблица1
field1,field2,field3,Transaction#,field4,New#
ABC,ABC,ABC,1,CFG,122
ABC,ABC,ABC,3,CFG,124
новая таблица2
field1;Transaction#;field3;field4;field5;New#
ABC;2;ABC;ABC;CFG;123
ABC;1;ABC;ABC;CFG;122
ABC;3;ABC;ABC;CFG;124