Ответ 1
Вы должны выбрать один из двух инструментов. Что касается sed
, это можно сделать следующим образом:
sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/' test.csv
Не уверен в awk
, но комментарий @shellter может помочь с этим.
У меня есть 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.
Спасибо.
Вы должны выбрать один из двух инструментов. Что касается sed
, это можно сделать следующим образом:
sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/' test.csv
Не уверен в awk
, но комментарий @shellter может помочь с этим.
Функция 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
Это может сработать для вас:
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
Итак, оказалось, что есть множество способов сделать это. Я получил его работу с 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 после прочтения ваших ответов.
Если у вас установлен 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.
Другое 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/
выполняется ли замена