#linux #awk #sed #replace
Вопрос:
У меня есть такой файл
abc|def||ghi|jklm||uv||xyz
abc|def||ghi|jklm|nopqrst|uv||xyz
abc|def||ghi|jklm|nopq"rst|uv||xyz
abc|def||ghi|jklm|"nopqrst"|uv||xyz
abc|def||ghi|jklm|"nopq"rst"|uv||xyz
abc|def||ghi|jklm|"nopq"r"st"|uv||xyz
6 — ю колонку можно было бы заключить в двойные кавычки. Я хочу заменить все вхождения двойных кавычек в этом поле на обратную косую черту-двойную кавычку («)
Я хочу, чтобы мой результат выглядел так
abc|def||ghi|jklm||uv||xyz
abc|def||ghi|jklm|nopqrst|uv||xyz
abc|def||ghi|jklm|nopq"rst|uv||xyz
abc|def||ghi|jklm|"nopqrst"|uv||xyz
abc|def||ghi|jklm|"nopq"rst"|uv||xyz
abc|def||ghi|jklm|"nopq"r"st"|uv||xyz
Я пробовал комбинации ниже, но каждый раз заканчивался коротко
sed -i 's/"/\"/2' file.txt (this replaces only 2nd occurrence)
sed -i 's/"/\"/2g' file.txt (this replaces only 2nd occurrence and all rest also)
В моем файле будут миллионы строк; поэтому мне может понадобиться только команда sed или awk.
Пожалуйста, помогите.
Комментарии:
1. У вас могут быть такие данные, как
"abc
илиxyz"
в 6-й колонке? То есть, присутствует только начальная или конечная цитата.2. Можете ли вы иметь
|
s в 6-й колонке, например ?"foo|bar"
У вас могут быть цитаты в любой другой колонке?
Ответ №1:
Вы можете использовать это awk
решение в любой версии awk
:
awk 'BEGIN {FS=OFS="|"} {
c1 = substr($6, 1, 1)
c2 = substr($6, length($6), 1)
s = substr($6, 2, length($6)-2)
gsub(/"/, "\"", s)
$6 = c1 s c2
} 1' file
abc|def||ghi|jklm||uv||xyz
abc|def||ghi|jklm|nopqrst|uv||xyz
abc|def||ghi|jklm|nopq"rst|uv||xyz
abc|def||ghi|jklm|"nopqrst"|uv||xyz
abc|def||ghi|jklm|"nopq"rst"|uv||xyz
abc|def||ghi|jklm|"nopq"r"st"|uv||xyz
Комментарии:
1. Спасибо тебе, Анубхава. Это идеально подходит для моих требований.
Ответ №2:
Если это не все, что вам нужно, отредактируйте свой вопрос, чтобы предоставить более репрезентативный образец ввода/вывода, включая случаи, когда это не работает:
$ sed 's/"/\"/g; s/|\"/|"/g; s/\"|/"|/g' file
abc|def||ghi|jklm||uv||xyz
abc|def||ghi|jklm|nopqrst|uv||xyz
abc|def||ghi|jklm|nopq"rst|uv||xyz
abc|def||ghi|jklm|"nopqrst"|uv||xyz
abc|def||ghi|jklm|"nopq"rst"|uv||xyz
abc|def||ghi|jklm|"nopq"r"st"|uv||xyz
Вышесказанное будет работать в любом sed.
Комментарии:
1. Спасибо тебе, Эд Мортон. Ваше решение является более общим и не ограничивается только столбцом № 6. Это, несомненно, будет полезно мне для моей будущей работы. Еще раз спасибо.
Ответ №3:
Это может сработать для вас (GNU sed):
sed -E 's/[^|]*/namp;n/6 # isolate the 6th field
h # make a copy
s/"/\"/g # replace " by "
s/\(")n|n\(")/1n2/g # repair start and end "s
H # append amended line to copy
g # get copies to current line
s/n.*n(.*)n.*n(.*)n.*/21/' file # swap fields
Окружите 6-е поле новыми строками и сделайте копию в области удержания.
Замените все "
» s » на "
» s «и удалите
» s «в начале и в конце поля, если поле начинается и заканчивается на "
» s
Добавьте измененную строку в копию и замените текущую строку удвоенной строкой.
Используя сопоставление с шаблоном, замените скопированную строку 6-го поля на измененное.