Игнорирование экранированных разделителей (запятых) с помощью awk?
Вопрос
Если бы у меня была строка с экранированными запятыми, например, так:
a,b,{c\,d\,e},f,g
Как я мог бы использовать awk для разбора этого на следующие элементы?
a
b
{c\,d\,e}
f
g
Решение
{
split($0, a, /,/)
j=1
for(i=1; i<=length(a); ++i) {
if(match(b[j], /\\$/)) {
b[j]=b[j] "," a[i]
} else {
b[++j] = a[i]
}
}
for(k=2; k<=length(b); ++k) {
print b[k]
}
}
- Разбить на массив
a
, используя ',
' в качестве разделителя - Построить массив
b
Отa
, объединяя строки , которые заканчиваются на '\
' - Печать массива
b
(Примечание:Начинается с 2, так как первый элемент пуст)
Это решение предполагает (на данный момент), что ',
' это единственный символ , который когда - либо экранировался с помощью '\
'- то есть, нет необходимости обрабатывать какие-либо \\
во входных данных, ни странных комбинаций, таких как \\\,\\,\\\\,,\,
.
Другие советы
{
gsub("\\\\,", "!Q!")
n = split($0, a, ",")
for (i = 1; i <= n; ++i) {
gsub("!Q!", "\\,", a[i])
print a[i]
}
}
Я не думаю, что awk имеет какую-либо встроенную поддержку для чего-то подобного.Вот решение, которое и близко не такое короткое, как у DigitalRoss, но при этом не должно подвергаться опасности случайного попадания в вашу выдуманную строку (!Q!).Поскольку он тестирует с помощью if
, вы также могли бы расширить его, чтобы быть осторожными с тем, есть ли у вас на самом деле \\,
в конце вашей строки, которая должна быть экранированной косой чертой, а не запятой.
BEGIN {
FS = ","
}
{
curfield=1
for (i=1; i<=NF; i++) {
if (substr($i,length($i)) == "\\") {
fields[curfield] = fields[curfield] substr($i,1,length($i)-1) FS
} else {
fields[curfield] = fields[curfield] $i
curfield++
}
}
nf = curfield - 1
for (i=1; i<=nf; i++) {
printf("%d: %s ",i,fields[i])
}
printf("\n")
}