Intereting Posts
Почему пакеты slackware воссоздают символические ссылки после установки? Я хочу отключиться автоматически, когда сигнал wpa_supplicant слаб Как настроить Ctrl + w как удалить слово в zsh Как подключиться к серверу ssh и запросить программные подсказки? Запуск VPN через Debian в маршрутизатор Как создать пользователя с заданным паролем на SuSE из командной строки? Ошибка компиляции buildroot Непоследовательные однократные и двойные щелчки в файловом менеджере GNOME / GTK btrfs на openSUSE не освобождает дисковое пространство Как написать сценарий оболочки для запуска нескольких команд в разных сеансах экрана? Восстановить снимок при загрузке Изменение текста на одном номере строки в нескольких текстовых файлах Как настроить OpenBSD pf только для входящего трафика из данных стран? Есть ли инструмент для сопоставления открытого текста eryptfs и зашифрованных имен файлов? Не удается заставить rc.local автоматически запускаться

Конкретная замена уровня столбца

Если у меня есть файл с столбчатыми записями, можно ли заменять определенные записи только из определенных столбцов и сохранять изменения в один и тот же файл?

Пример файла abc.txt :

 SR|FRUITS|COLOR| 1|Apple|Red| 2|Mango|Yellow| 3|Orange|Orange| 4|W.Melon|Green| 

Необходимо изменить Orange от фруктов до Orange_Edit . Однако оранжевый цвет не должен быть затронут.

Вы можете сделать это за 2 шага с помощью awk like

 awk '{$2="VAL";print}' input_file > temp_file mv temp_file input_file 

Это разделит входной файл на пробел, замените значение во втором столбце (используйте любое другое число, отличное от 2 для другого столбца), так что теперь оно будет «VAL». Если вы не измените его с OFS разделителем поля вывода будет пробел. Если вы хотите добавить что-то еще, внутри кавычек, что-то вроде «BEGIN {OFS =" \ t "} … ', чтобы установить разделитель выходных полей на все, что вы хотите.

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

Чтобы сделать эту работу для редактирования в вашем случае, вы можете:

 awk -F\| 'BEGIN {OFS="|";} $2~/^Orange$/ {$2="Orange_edit";} {print}' abc.txt > temp_file mv temp_file abc.txt 

Это сначала говорит awk разделить поля на основе | передавая -F\| , Затем мы настраиваем наш вывод для использования | для разделителя вывода (по умолчанию это пробел), сделав первый блок кода (часть, которая соответствует BEGIN, ключевое слово в awk , совпадающее с началом выполнения) и установив наш OFS или выходной полевой разделитель. Как заметил Отеус, мы могли бы {OFS=FS} установить выходной разделитель таким же, как и входной.

После этого мы начинаем смотреть на линии. Мы сравниваем второе поле, на которое ссылается $2 , затем проверяем, совпадает ли оно с регулярным выражением, используя ~ . После ~ является регулярным выражением, которое мы хотим сопоставить, ^ здесь означает совпадение начала поля, тогда у нас есть строка «Оранжевый», а затем $ которая соответствует концу поля. Поскольку это строго закодированная строка, которую также справедливо заметил Otheus, мы могли бы просто проверить здесь равенство строк и сделать $2=="Orange" и пропустить обработку регулярных выражений, поскольку на этот раз на самом деле ничего не делает. Если это совпадение завершает блок кода в {} после его выполнения, который сохранит новое значение во втором поле.

Наконец, мы выполняем последний блок кода {print} для каждой строки, но когда наше совпадение «оранжевое» преуспело выше, мы изменили значение второго поля, поэтому оно печатает с нашим новым значением вместо старого.

awk обычно печатает на экране (видимо, новый gawk имеет возможность оптимизировать эту часть), поэтому мы сохраняем это в файле, а затем переместите этот файл обратно в исходное имя.

Есть много способов сделать это. Простейшими являются, вероятно, awk и perl :

  1. GNU gawk . Если у вас установлена ​​относительно новая версия gawk , вы можете сделать встроенное редактирование следующим образом:

     gawk -i inplace -F"|" -vOFS="|" '$2=="Orange"{$2="Orange_Edit"}1;' file 

    -i inplace сообщает gawk чтобы отредактировать файл inplace, -F"|" устанавливает разделитель полей в | и -vOFS="|" устанавливает разделитель выходного поля в | также. Сценарий устанавливает второе поле ( $2 ) в значение Orange_Edit только если второе поле было Orange . 1; является сокращением awk для «распечатывать текущую строку.

  2. Perl

     perl -i -F"\|" -lane '$F[1]="Orange_Edit" if $F[1] eq "Orange"; print join "|",@F' file 

    -a заставляет Perl действовать как awk и разделить строки на значение, заданное -F , сохраняя полученные поля в массиве @F . Затем скрипт устанавливает второе поле ( $F[1] , массивы начинаются с 0) до Orange_Edit если его исходное значение было Orange . Затем поля объединяются | и напечатаны.

  3. Если вы просто хотите изменить первое появление Orange , вы можете упростить и использовать

     sed -i 's/Orange/Orange_Edit/' file 

    Вы можете сделать это немного более надежным, если только совместить целые поля:

     sed -i 's/|Orange|/|Orange_Edit|/' file 

Вы можете использовать perl :

 $ perl -i.bak -F'\|' -aple 's/Orange/Orange_Edit/ if $F[1] eq "Orange"' file 

или более безопасная версия:

 $ perl -i.bak -F'\|' -aple '$F[1]=~s/^Orange$/Orange_Edit/; $_=join "|",@F' file