
У меня есть набор данных, содержащий контактную информацию студентов, пример набора данных выглядит следующим образом:
First Name, Last Name, Address, Phone Number
John, Doe, "House # 11, Street xyz, Road, Area",00000000
Sara, Taylor, "Jake Lake%, Apartment #22, Main Road, Area XYZ", 00000000
Я запускаю следующую команду для замены,внутри столбца Адрес в|для загрузки его в БД.
awk '!(NR%2){gsub(",","|")} {printf RFS $0} {RFS="\""}' RS=\" fileName.txt > output.txt
Проблема, с которой я столкнулся, заключается в том, что всякий раз, когда я запускаю эту команду, она возвращает мне следующую ошибку. Изначально она работала нормально.
awk: run time error: not enough arguments passed to printf(""Jake Lake%, Apartment #22, Main Road, Area XYZ")
Есть ли решение этой проблемы? Я заметил, что%приходит по адресу, в этом проблема?
решение1
- Для надежности никогда не делайте
printf $0
, всегда используйтеprintf "%s", $0
вместо этого , так как первый вариант не сработает, если ваш ввод содержитprintf
символы форматирования (как вы сейчас видите). То же самое относится к использованиюprintf
с любыми входными данными. - Для ясности и надежности никогда не используйте имена переменных, состоящие только из заглавных букв, например,
RFS
чтобы избежать конфликтов с именами встроенных переменных и чтобы не запутывать код, создавая впечатление, что вы используете встроенную переменную, хотя это не так. - Для удобства чтения не устанавливайте переменные, например
RS
, после вашего скрипта, если только вам не нужно задать им разные значения для разных входных файлов; устанавливайте переменные до или в начале вашего скрипта, чтобы при чтении вашего скрипта мы видели, как они устанавливаются, прежде чем мы увидим их использование. - Для эффективности, простоты и надежности первым аргументом *sub() является регулярное выражение, а не строка, поэтому используйте вокруг него разделители regexp (
/.../
), а не string ("..."
), если только по какой-то причине вам НЕ НУЖНО динамическое, а не статическое регулярное выражение. - Для ясности и удобства поддержки, если у вас есть 2 переменные, которые должны иметь одинаковое значение, например
RS
иRFS
, не устанавливайте для них по отдельности одно и то же значение, напримерRS="\""; RFS="\""
, либо устанавливайте для них это значение вместе, например ,RS=RFS="\""
либо устанавливайте для одной из них значение другой, напримерRS="\""; RFS=RS
.
Вот как правильно написать код в вашем вопросе:
$ awk -v RS='"' '!(NR%2){gsub(/,/,"|")} {printf "%s%s", rfs, $0; rfs=RS}' file
First Name, Last Name, Address, Phone Number
John, Doe, "House # 11| Street xyz| Road| Area",00000000
Sara, Taylor, "Jake Lake%| Apartment #22| Main Road| Area XYZ", 00000000
Чтобы сделать что-то еще с CSV с помощью awk, см.какой-самый-надежный-способ-эффективно-разобрать-csv-с-помощью-awk.
решение2
Ошибка, которую вы получаете, возникает из-за использования конкатенации значения RFS
(пустой переменной) и $0
в качестве строки формата с printf
.
Ваш файл является допустимым CSV-файлом, за исключением пробелов после некоторых разделительных запятых (что портит цитирование поля Address
; цитируемое поле должно иметь начальный символ кавычек сразу после разделителя). Мы можем исправить это с помощью csvformat
(часть csvkit изhttps://csvkit.readthedocs.io/en/latest/):
$ csvformat --skipinitialspace file.csv >fixed-file.csv
$ cat fixed-file.csv
First Name,Last Name,Address,Phone Number
John,Doe,"House # 11, Street xyz, Road, Area",00000000
Sara,Taylor,"Jake Lake%, Apartment #22, Main Road, Area XYZ",00000000
База данных, способная анализировать CSV, должна иметь возможность прочитать эти данные как есть.
Если вы по-прежнему хотите заменить все встроенные запятые на |
, просто измените разделитель файла на что-то другое, нежели запятая (ниже я буду использовать табуляцию), замените все оставшиеся запятые на вертикальные линии и снова вернитесь к использованию запятых в качестве разделителей.
Мы можем сделать это непосредственно с исходными данными:
$ csvformat --skipinitialspace --out-tabs file.csv | tr ',' '|' | csvformat --tabs >fixed-file.csv
$ cat fixed-file.csv
First Name,Last Name,Address,Phone Number
John,Doe,House # 11| Street xyz| Road| Area,00000000
Sara,Taylor,Jake Lake%| Apartment #22| Main Road| Area XYZ,00000000
Короткие варианты различных длинных опций: -S
for --skipinitialspace
, -T
for --out-tabs
и -t
for --tabs
.