Я хочу заменить точку в поле заголовка (поле2) csv точкой, за которой следует пробел:

Csv пример:

8389383, hello my.friend,839083083,3390903

Предполагаемый результат:

8389383, hello my. friend,839083083,3390903

Я могу успешно заменить точку в csv пробелом, используя только эту строку:

sed -r ':b s/^([^,]*,[^,]*)\./\1 /g; t b' csv

Однако я хочу заменить точку на точку, за которой следует пробел. Я пытался:

sed -r ':b s/^([^,]*,[^,]*)\./\1. /g; t b' csv

Но это зависает и результата не дает.

Что я могу добавить в строку, чтобы разрешить это?

РЕДАКТИРОВАТЬ. Чтобы добавить, в поле 2 (поле заголовка) может быть более одной точки, которую я хочу заменить. Я также не хочу, чтобы это правило применялось к любым другим полям в CSV.

1
neilH 3 Сен 2016 в 19:02

4 ответа

Лучший ответ

awk лучше всего подходит для такого рода работ

Для замены всех точек во втором поле выполните

 awk -v FS="," -v OFS="," '{gsub(/\./,". ",$2)}1' file.csv > tmpfile && mv tmpfile file.csv

8389383, hello my. friend,839083083,3390903
8389383, hello my. fri. end,839083083,3390903
5
sjsam 3 Сен 2016 в 16:46

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

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

Хитрость заключается в том, чтобы превратить . в something else (я предпочитаю символ новой строки, поскольку он уникален по дизайну seds), а затем глобально изменить это something else на whatever в качестве последняя операция на линии.

Альтернативой является копирование линии, изменение части и рекомбинация линии, используя части из копии, которые вы не хотите изменять:

sed -r 's/,/\n/;s/,/\n/;h;s/\./& /g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2,\1,/' file
0
potong 4 Сен 2016 в 10:04
$ cat file.csv 
8389383, hello my.friend, 839083083, 3390903
8389383, hello my.fri.end, 839083083, 3390903

$ perl -i -F, -e '$F[1] =~ s/\./. /g; print join(",",@F)' file.csv 

$ cat file.csv 
8389383, hello my. friend, 839083083, 3390903
8389383, hello my. fri. end, 839083083, 3390903
  • -F, разделяет каждую строку на , и сохраняет ее в массиве @F. Параметр -F неявно устанавливает -a и -n. Дополнительную информацию см. В разделе Командные переключатели perldoc.
  • join(",",@F) присоединяются к массиву с , в качестве разделителя. Не знаю, есть ли в perl неявный способ распечатать измененный массив с тем же разделителем ввода
0
Sundeep 5 Сен 2016 в 08:21

Как насчет этого:

sed -i -e 's/^\([^,]*,[^.,]*\)\.\([^,]*\)/\1. \2/' file.csv

Изменить . Если в поле указано несколько точек, вы не можете сделать это с помощью sed. А вот однострочник perl:

perl -i -pe 'sub t {($s)=@_; $s=~s/\./. /g; $s}; s/^[^,]*,\K([^,]*)/t($1)/e;' file.csv

Объяснение: С помощью команды s/// мы находим первое поле ([^,]*,), пропускаем его (\K), а затем находим второе поле (([^,]*)). Для этого поля мы выполняем функцию t, которая выполняет простую подстанцию.

1
redneb 3 Сен 2016 в 16:56