Подтвердить что ты не робот

Замена на месте

У меня есть CSV. Я хочу отредактировать 35-е поле CSV и записать изменение обратно в 35-е поле. Это то, что я делаю на bash:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g'

Итак, я вытаскиваю 35-ю запись с помощью awk, а затем заменяю "0" в исходной позиции в строке "+91". Это работает, и я получаю желаемый результат на консоли.

Теперь я хочу, чтобы эта новая запись записывалась в файл. Я думаю, что функция sed "in -place" заменяется, но этот файл требует и входной файл. В приведенной выше команде я не могу предоставить входной файл, потому что моя основная команда awk и sed берут входные данные из awk.

Спасибо.

4b9b3361

Ответ 1

Вы должны выбрать один из двух инструментов. Что касается sed, это можно сделать следующим образом:

sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/' test.csv 

Не уверен в awk, но комментарий @shellter может помочь с этим.

Ответ 2

Функция in-place sed называется неназванным, так как она не редактирует файл на месте. Вместо этого он создает новый файл с тем же именем. например:

$ echo foo > foo
$ ln -f foo bar
$ ls -i foo bar  # These are the same file
797325 bar  797325 foo
$ echo new-text > foo  # Changes bar
$ cat bar
new-text
$ printf '/new/s//newer\nw\nq\n' | ed foo  # Edit foo "in-place"; changes bar
9
newer-text
11
$ cat bar
newer-text
$ ls -i foo bar  # Still the same file
797325 bar  797325 foo
$ sed -i s/new/newer/ foo   # Does not edit in-place; creates a new file
$ ls -i foo bar
797325 bar  792722 foo    

Так как sed фактически не редактирует файл на месте, а пишет новый файл, а затем переименовывает его в старый файл, вы также можете сделать то же самое.

awk ... test.csv | sed ... > test.csv.1 && mv test.csv.1 test.csv

Существует неправильное представление о том, что использование sed -i каким-то образом предотвращает создание временного файла. Это не. Это просто скрывает от вас факт. Иногда абстракция - это хорошо, но в других случаях это ненужное обфускация. В случае sed -i он является последним. Оболочка действительно хороша при манипулировании файлами. Используйте его по назначению. Если вам нужно отредактировать файл на месте, не используйте поточную версию ed; просто используйте ed

Ответ 3

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

sed -i 's/[^,]*/+91/35' test.csv

EDIT:

Чтобы заменить передний ноль в 35-м поле:

sed 'h;s/[^,]*/\n&/35;/\n0/!{x;b};s//+91/' test.csv

или более просто:

|sed 's/^\(\([^,]*,\)\{34\}\)0/\1+91/' test.csv

Ответ 4

Итак, оказалось, что есть множество способов сделать это. Я получил его работу с sed, как показано ниже:

sed -i 's/0\([0-9]\{10\}\)/\+91\1/g' test.csv

Но это немного сложно, поскольку он будет редактировать любую запись, которая соответствует критериям. однако в моем случае он работает нормально.

Аналогичная реализация вышеуказанной логики в perl:

perl -p -i -e 's/\b0(\d{10})\b/\+91$1/g;' test.csv

Опять же, такое же предостережение, как упоминалось выше.

Более точный способ сделать это, как показано Лев Левицкий, потому что он будет действовать конкретно на 35-ом поле

sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/g' test.csv

Для более сложных ситуаций мне придется рассмотреть возможность использования любого из модулей csv perl.

Спасибо всем за ваше время и вклад. Я обязательно узнаю больше о sed/awk после прочтения ваших ответов.

Ответ 5

Если у вас установлен moreutils, вы можете просто использовать инструмент sponge:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g' | sponge test.csv

sponge впитывает вход, закрывает входной канал (stdin) и только затем открывается и записывается в файл test.csv.

По состоянию на 2015 год, moreutils доступен в репозиториях пакетов нескольких основных дистрибутивов Linux, таких как Arch Linux, Debian и Ubuntu.

Ответ 6

Другое perl-решение для редактирования 35-го поля на месте:

perl -i -F, -lane '$F[34] =~ s/^0/+91/; print join ",",@F' test.csv

Используются следующие параметры командной строки:

  • -i отредактируйте файл на месте
  • -n цикл вокруг каждой строки входного файла
  • -l удаляет новые строки перед обработкой и добавляет их обратно
  • -a режим автосплит - разделение входных строк на массив @F. По умолчанию разбивается на пробелы.
  • -e выполнить код perl
  • -F модификатор авторасширения, в этом случае разбивается на ,

@F - это массив слов в каждой строке, индексированный начиная с 0 $F[34] является элементом 35 массива
s/^0/+91/ выполняется ли замена