sed - Заменить запятую после первого совпадения с регулярным выражением - PullRequest
0 голосов
/ 20 мая 2019

я пытаюсь выполнить следующую подстановку в строках общего формата:

BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC, .......

, как вы видите, проблема в том, что это файл, разделенный запятыми, со специальным полем, содержащим десятичную запятую.Я хотел бы заменить это точкой.

Я пытался это сделать, чтобы заменить первое вхождение шаблона после матча, но безрезультатно, может ли кто-нибудь мне помочь?

sed -e '/,"/!b' -e "s/,/./"
sed -e '/"/!b' -e ':a' -e "s/,/\./"

Заранее спасибо.Решение awk или perl также поможетВот попытка awk:

gawk -F "," 'substr($10, 0, 3)==3 && length($10)==12 { gsub(/,/,".", $10); print}'

, что дало тот же файл без изменений.

Ответы [ 6 ]

3 голосов
/ 20 мая 2019

CSV-файлы должны быть проанализированы в awk с правильной переменной FPAT, которая определяет, что составляет действительное поле в таком файле. Как только вы это сделаете, вы можете просто перебрать поля, чтобы выполнить замену, необходимую вам

gawk 'BEGIN { FPAT = "([^,]+)|(\"[^\"]+\")"; OFS="," } 
       { for(i=1; i<=NF;i++) if ($i ~ /[,]/) gsub(/[,]/,".",$i);}1' file

См. мой ответ , чтобы понять, как определить и проанализировать содержимое файла CSV с помощью переменной FPAT. Также см. Сохранение изменений на месте с помощью awk для внесения изменений в файлы на месте, например sed -i''.

1 голос
/ 20 мая 2019

Если ваш ввод всегда соответствует формату только одного поля в кавычках, содержащего 1 запятую, тогда все, что вам нужно:

$ sed 's/\([^"]*"[^"]*\),/\1./' file
BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109.07",DF,CCCCCCCCCCC, .......

Если это сложнее, чем это, тогда посмотрите Какой самый надежный способэффективно анализировать CSV с помощью awk? .

1 голос
/ 20 мая 2019

Это может работать для вас (GNU sed):

sed -E ':a;s/^([^"]*("[^",]*"[^"]*)*"[^",]*),/\1./;ta' file

Это регулярное выражение соответствует , в паре " и заменяет его на ..Регулярное выражение привязывается к началу строки и, следовательно, должно повторяться до тех пор, пока никакие другие совпадения не будут сопоставлены, следовательно, команды :a и ta, которые приводят к повторному выполнению подстановки, пока любая подстановка успешна.

NB Решение предполагает, что все двойные кавычки совпадают и что двойные кавычки не заключаются в кавычки, т.е. \" не появляется в строке.

1 голос
/ 20 мая 2019

Следующие sed преобразуют все десятичные разделители в числовые поля в кавычках:

 sed 's/"\([-+]\?[0-9]*\)[,]\?\([0-9]\+\([eE][-+]\?[0-9]+\)\?\)"/"\1.\2"/g'

См .: https://www.regular -expressions.info / floatingpoint.html

0 голосов
/ 20 мая 2019

Чтобы использовать регулярное выражение как в perl, вы должны активировать расширенное регулярное выражение с помощью -r.Поэтому, если вы хотите заменить все числа и опустить знак ", вы можете использовать это:

echo 'BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC, .......'|sed -r 's/\"([0-9]+)\,([0-9]+)\"/\1\.\2/g'

Если вы хотите заменить только первое вхождение, вы можете использовать это:

echo 'BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC, .......'|sed -r 's/\"([0-9]+)\,([0-9]+)\"/\1\.\2/1'

https://www.gnu.org/software/sed/manual/sed.txt

0 голосов
/ 20 мая 2019

Если у вас есть это: BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC

Попробуйте это: awk -F',' '{print $1,$2,$3,$4"."$5,$6,$7}' filename | awk '$1=$1' FS=" " OFS=","

Вывод будет: BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109.07",DF,CCCCCCCCCCC

Вам просто нужно знать номера полей для замены разделителя полей между ними.

...