Вдохновленный другим ответом, вот более простой контекстный обработчик ошибок:
trap '>&2 echo Command failed: $(tail -n+$LINENO $0 | head -n1)' ERR
Вы также можете использовать awk вместо tail & head , если необходимо.
Предполагая, что данные являются простыми данными CSV, т. е. ни одно поле не содержит встроенных разделителей или новых строк:
awk -F ';' '
{
print > "file" $2 ".csv"
print > "file" $2 $6 ".csv"
}' file1.csv
Это печатает каждую строку дважды, один раз в файл, заданный только значением второго поля, и один раз в файл, заданный комбинацией значений второго и шестого полей. Каждое имя выходного файла будет иметь префикс строки file
и суффикс строки .csv
в соответствии с текстом вопроса.
Проверка значений двух полей, используемых в именах файлов, не выполняется.
Если вы хотите включить название страны из четвертого поля:
awk -F ';' '
{
print > "file_" $2 "-" $4 ".csv"
print > "file_" $2 "-" $4 "_" $6 ".csv"
}' file1.csv
Для заданных данных будут созданы следующие файлы
file_AD-Andorra.csv
file_AD-Andorra_type_1.csv
file_AD-Andorra_type_2.csv
file_NL-Netherlands.csv
file_NL-Netherlands_type_2.csv
file_US-United States.csv
file_US-United States_type_2.csv
Вышеописанное будет хорошо работать в системе, использующей GNU awk
. Другие реализации awk
могут столкнуться с проблемами, связанными с одновременным сохранением слишком большого количества файлов открытыми для записи. В таких реализациях awk
вам придется быть умнее и не забывать закрывать файлы после записи в них. Когда файл закрыт, нужно не забыть напечатать с >>
в следующий раз, когда данные должны быть записаны в файл, иначе файл будет усечен.
awk -F ';' '
function do_print(name) {
if (seen[name] == 1) print >>name # append to file
else print >name # first write, truncate file
close(name)
seen[name] = 1
}
{
do_print("file_" $2 "-" $4 ".csv")
do_print("file_" $2 "-" $4 "_" $6 ".csv")
}' file1.csv
Это также заставит код работать с awk
в OpenBSD, с которым вы не можете print >
в выражение.
Дополнительно (просто для удовольствия ):Заставить код awk
выводить некоторую статистику:
awk -F ';' '
function do_print(name) {
if (seen[name] > 0) print >>name # append to file
else print >name # first write, truncate file
close(name)
seen[name]++
}
{
do_print("file_" $2 "-" $4 ".csv")
do_print("file_" $2 "-" $4 "_" $6 ".csv")
}
END {
for (name in seen)
printf "Wrote %d lines to \"%s\"\n", seen[name], name >"/dev/stderr"
}' file1.csv
Это записывает некоторую статистику в поток ошибок в конце обработки. Для приведенных данных:
Wrote 1 lines to "file_NL-Netherlands.csv"
Wrote 1 lines to "file_US-United States_type_2.csv"
Wrote 1 lines to "file_AD-Andorra_type_1.csv"
Wrote 2 lines to "file_AD-Andorra.csv"
Wrote 1 lines to "file_NL-Netherlands_type_2.csv"
Wrote 1 lines to "file_US-United States.csv"
Wrote 1 lines to "file_AD-Andorra_type_2.csv"