У меня есть входной файл, разделенный запятыми ( ,
). Есть некоторые поля, заключенные в двойные кавычки, в которых есть запятая. Вот пример строки
123,"ABC, DEV 23",345,534.202,NAME
Мне нужно удалить все запятые внутри двойных кавычек, а также двойные кавычки. Таким образом, приведенная выше строка должна быть проанализирована, как показано ниже
123,ABC DEV 23,345,534.202,NAME
Я попробовал следующее, используя, sed
но не давая ожидаемых результатов.
sed -e 's/\(".*\),\(".*\)/\1 \2/g'
Любые быстрые трюки sed
, awk
или любая другая утилита Unix, пожалуйста?
text-processing
sed
awk
csv
холодный морской тропический воздух
источник
источник
Ответы:
Если кавычки сбалансированы, вы захотите удалить запятые между каждой другой кавычкой, это можно выразить
awk
так:Выход:
объяснение
Команда
-F"
make awk отделяет строку от двойных кавычек, что означает, что любое другое поле будет текстом, заключенным в кавычки. Цикл for запускаетсяgsub
, за исключением глобально заменителя, в любом другом поле, заменяя запятую (","
) ничем (""
).1
В конце вызывает кодовый блок по умолчанию:{ print $0 }
.источник
gsub
и объяснить вкратце, как работает этот лайнер? Пожалуйста.{ print $0 }
. Я добавил это к объяснению также.prefix,"something,otherthing[newline]something , else[newline]3rdline,and,things",suffix
(то есть: несколько строк и вложенные символы "," в любом месте в многострочном двойном кавычке: вся"...."
часть должна быть объединена, а внутренняя часть,
должна быть заменен / удален ...): ваш сценарий не будет видеть пары двойных кавычек в этом случае, и это не очень легко решить (нужно «воссоединиться» со строками, которые находятся в «открытом» (то есть нечетном) двойная кавычка ... + будьте особенно осторожны, если\"
внутри строки также есть экранированный символ)awk -F'"' -v OFS='"' '{ for (I=1; i<=NF; i+=2) gsub(",", "|", $i) } 1' infile
Есть хороший ответ, используя sed просто один раз с циклом :
Объяснение:
:a;
это этикетка для дальней ветвиs/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /
может содержать 3 закрытые части[^"]*,\?\|"[^",]*",\?
соответствует строке, не содержащей двойных кавычек, может сопровождаться запятой или строкой, заключенной в две двойных кавычки, без запятой и может сопровождаться запятой.ta
зацикливается,:a
если предыдущаяs/
команда внесла некоторые изменения.источник
Общее решение, которое также может обрабатывать несколько запятых между сбалансированными кавычками, требует вложенной замены. Я реализую решение в Perl, которое обрабатывает каждую строку данного ввода и заменяет запятые только в каждой другой паре кавычек:
или короче
Вы можете либо передать текст, который вы хотите обработать, в команду, либо указать текстовый файл для обработки в качестве последнего аргумента командной строки.
источник
[^\\]
приведет к нежелательному эффекту совпадения последнего символа внутри кавычек и удаления его (не \ символ), т. Е. Вы не должны использовать этот символ. Попробуй(?<!\\)
вместо этого.[^"]*
чтобы сделать матч не жадным (т.е. соответствует всем от одного"
до следующего"
):perl -pe 's/"([^"]+)"/($match = $1) =~ (s:,::g);$match;/ge;'
. Он не признает диковинную идею , что цитата может быть экранированы с обратной косой черты :-)[^"]*
подход или явный не жадный подход потреблял меньше времени процессора.Я бы использовал язык с правильным парсером CSV. Например:
источник
Ваши вторые цитаты неуместны:
Кроме того, использование регулярных выражений, как правило, соответствует самой длинной части текста, что означает, что это не сработает, если в строке более одного поля в кавычках.
Способ, который обрабатывает несколько полей в кавычках в sed
Это также способ решить эту проблему, однако, с помощью ввода, которое может содержать более одной запятой на поле в кавычках, первое выражение в sed должно будет повторяться столько раз, сколько максимальное запятое в одном поле, или до не меняет выход вообще.
Выполнение sed с более чем одним выражением должно быть более эффективным, чем выполнение нескольких процессов sed, и "tr", выполняемый с открытыми каналами.
Однако это может иметь нежелательные последствия, если ввод не отформатирован должным образом. то есть вложенные кавычки, неопределенные кавычки.
Используя работающий пример:
Выход:
источник
sed -r ':r; s/("[^",]+),([^",]*)/\1 \2/g; tr; s/"//g'
.В Perl - вы можете использовать это
Text::CSV
для анализа, и сделать это тривиально:Вы можете печатать с помощью,
Text::CSV
но он сохраняет кавычки, если вы делаете. (Хотя, я бы предложил - вместо зачистки кавычки для вывода, вы можете просто разобрать , используяText::CSV
в первую очередь).источник
Я создал функцию для циклического прохождения каждого символа в строке.
Если символ является кавычкой, то проверка (b_in_qt) помечается как истинная.
Хотя b_in_qt имеет значение true, все запятые заменяются пробелом.
b_in_qt устанавливается в false при обнаружении следующей запятой.
источник