Замена первого экземпляра переключаемого значения в gvim с помощью awk - PullRequest
2 голосов
/ 18 марта 2019

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

ввод:

54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 76 78  
77 564 65 76 45 

вывод:

54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 91 78  
77 564 65 76 45  

Таким образом, первое вхождение 76 в четвертом столбце заменяется на 91.
Это то, что я пытался сделать, используя awk:

awk '{count=0;if ($4 == 76 && count < 1){ gsub("91","76")} count++; print}' input > output 

Но это не помогает, кто-нибудь может что-то подсказать?

Ответы [ 6 ]

4 голосов
/ 18 марта 2019

Небольшая настройка ответа stack0114106 , чтобы сделать его еще более кратким:

awk '!t && $4==76 { $4=91; t=1;} 1 ' file

Переменные в awk, которые не были назначены, будут иметь 0 или пустое строковое значение,отрицание даст true.
И я поставлю !t перед тем, как другое уравнение сравнения относится к эффективности, поскольку && является оператором быстрого вызова, он остановит выполнение второй части, когда первая часть оценивается как false.

Последний 1 должен создать там true, условие без блока будет иметь {print $0} подразумеваемый блок.

3 голосов
/ 18 марта 2019

Не могли бы вы попробовать следующее (используя этот подход, мы упоминаем все значения в переменных и ничего не кодируем жестко, для любых дальнейших изменений значений просто измените значения переменных, и программа все равно должна работать).

awk -v column="4" -v count="1" -v value="76" -v new_value="91" '($column == value){if(++num==count){$column=new_value}} 1' Input_file

Или добавление формы решения не с одним вкладышем.

awk -v column="4" -v count="1" -v value="76" -v new_value="91" '
($column == value){
  if(++num==count){
      $column=new_value
  }
}
1
'  Input_file

Вывод будет следующим.

54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 91 78
77 564 65 76 45


РЕДАКТИРОВАНИЕ: исправление попытки OP 'и добавление деталей исправлений тоже.

Код следует изменить на:

awk '{if ($4 == 76){if(++count == 1){sub("^" 76 "$","91",$4)}};print}' Input_file

Объяснение вышеуказанного FIX кода OP:

  • count=0 - это ошибка здесь, так как каждый раз, когда читается новая строка, значение счетчика будет равно 0, и программа НИКОГДА не узнает, сколько раз 76 входило в 4-е поле, поэтому я удалил его.
  • Теперь поместите count<0, которое на самом деле должно быть ++count==1 и должно быть внутри БЛОКА условия $4==76 почему, поскольку условие eve НЕ ИСТИНА ($4==76), значение переменной count постоянно увеличивается, поэтому давайте увеличим тогда, когда условие $4==76 имеет значение ИСТИНА, и тогда оно будет правильно вести счет.
  • СЕЙЧАС я исправил gsub даже выше - ИСПРАВЛЕНО, но код все равно НЕ будет работать, потому что шаблон (g)sub равен sub(current_value,replaced_value), поэтому вы заменяете 91 на 76, который полностью противоположен вашему запросу, и после этого ИСПРАВИТЬ ваш код должен хорошо работать:)
2 голосов
/ 18 марта 2019

Попробуйте этот простой awk

awk -v t=1 ' $4==76 && t==1 { $4=91; t=0;} 1 ' file

Чтобы исправить вашу попытку, просто оберните инициализацию счетчика в блоке BEGIN и поменяйте местами совпадения и замените входные данные в gsub, т.е. 76 и 91

awk ' BEGIN {count=0; } { if ($4 == 76 && count < 1){ gsub("76","91"); count++; } print}  ' input > output 

с вашими входами

$ cat himanshu.txt
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 76 78
77 564 65 76 45

$ awk -v t=1 ' $4==76 && t==1 { $4=91; t=0;} 1 ' himanshu.txt
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 91 78
77 564 65 76 45

$
1 голос
/ 18 марта 2019

Вот мое решение

awk -v count=0 -v replace=76 -v replaceWith=91 'count==0&&$4==76{gsub("^" replace "$", replaceWith, $4); count++}1' sourceFile

используются три переменные count, replace и replaceWith count - для подсчета числа поисковых запросов. Я увеличил значение после того, как нашел условие поиска replace и убедился, что больше не возвращаюсь в действие с помощью выражения count == 0

replace может быть любым значением из списка ... не должно быть жестко закодировано. Как и в случае с replaceWith, вы хотите заменить значение на

Результат

awk -v count=0 -v replace=76 -v replaceWith=91  'count==0&&$4==76{sub("^" replace "$", replaceWith, $4); count++}1' sourceFile
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 91 78
77 564 65 76 45

изменил скрипт после обратной связи. заменено gsub на $4 = replaceWith

awk -v count=0 -v replace=76 -v replaceWith=91 'count==0 && $4==replace{$4 = replaceWith; count++}1' sourceFile
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 91 78
77 564 65 76 45
1 голос
/ 18 марта 2019

Ваш заголовок сбивает с толку: из gvim вы хотите вызвать awk, чтобы отредактировать файл, который вы сейчас редактируете?Сделайте это в vim:

  1. перейдите к началу файла: g g
  2. ищите 76 в 4-м поле: / ^[^ ]\+ [^ ]\+ [^ ]\+ 76 Введите
  3. перейти к 4-му полю: 3 w
  4. изменитьслово: c w 91 Esc
1 голос
/ 18 марта 2019

Вы можете использовать следующую команду awk, если ваше значение 76 может находиться в любом столбце:

awk '{for(i=1;i<=NF;i++){if($i == 76 && count < 1){count++; $i=91}}print}' input
54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 91 78
77 564 65 76 45
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...