Увеличить индекс в файле

Увеличить индекс в файле

Ладно, похоже, я не могу найти способ сделать то, что мне нужно.

Допустим, у меня есть текстовый файл A, например такой:

(freqBiasL2[27])      
(SatBiasL1[27])       
(defSatBiasL2_L1[27]) 
(defSatBiasSlope[27]) 
(defSatBiasSigma[27]) 

(freqBiasL2[28])      
(SatBiasL1[28])       
(defSatBiasL2_L1[28]) 
(defSatBiasSlope[28]) 
(defSatBiasSigma[28]) 

(freqBiasL2[29])      
(SatBiasL1[29])       
(defSatBiasL2_L1[29]) 
(defSatBiasSlope[29]) 
(defSatBiasSigma[29])

и т. д. Я хочу изменить индекс между скобками [] так, чтобы каждый индекс i был = i+3.

Я пробовал использовать комбинацию цикла for и sed, но не работает

for i in {27..107..1}
do
    i_new=$((i+3))
    sed -e 's/\['$i'\]/\['$i_new'\]/' prova.txt 

done

Проблема в том, что он изменит первые 27 на 30, но при следующих интерпретациях найдет 2 блока с индексом 30 (измененный и исходный).

Как это сделать, не перезаписывая уже измененные индексы?

Хорошо, спасибо, я редактирую свой вопрос для улучшения: как я могу сделать что-то подобное, если у меня есть 2 индекса, например:

(freqBiasL2[32][100])
(SatBiasL1[32][101])
(defSatBiasL2_L1[32][102])
(defSatBiasSlope[32][103])
(defSatBiasSigma[32][104])

и я хочу увеличить только второй индекс, игнорируя первый?

решение1

Используйте perl:

perl -pe 's/(?<=\[)(\d+)(?=\])/$1+1/ge' prova.txt

Объяснение:

  • -pозначает цикл по каждой строке и вывод результата после каждой строки
  • -eопределяет выражение, которое будет выполняться в каждой строке
  • s/from/to/делает простую замену
  • s/(\d+)/$1+1/geсопоставляет одну или несколько цифр, записывает их в $1, а затем eмодификатор в конце сообщает Perl, что строка подстановки является выражением: $1+1подставляет значение $1плюс 1. gМодификатор означает, что эту подстановку следует выполнять глобально, т. е. более одного раза в строке.
  • (?<=\[)является положительным утверждением нулевой длины lookbehind. Это означает, что то, что следует за ним, соответствует только если ему предшествует [(что необходимо экранировать с помощью, \поскольку [это специальный токен в регулярных выражениях). Нулевая длина означает, что это не часть того, что будет заменено.
  • (?=\])является положительным утверждением нулевой длины. Это означает, что то, что идет до него, соответствует только если за ним следует ](снова экранировано).

Таким образом, это возьмет все числа между [и ]и увеличит это число.

решение2

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

awk -F '[\\[\\]]' '{if ($2) { sub($2, $2 + 3)}} 1' prova.txt

На самом деле, это можно немного сократить до:

awk -F '[\\[\\]]' '$2 { sub($2, $2 + 3)} 1' prova.txt

решение3

Я знаю, что вы уже решили свою проблему, но, к вашему сведению, вы могли бы решить ее, внеся очень простую модификацию в свой код: инвертировав последовательность, которую вы перебираете в цикле.

Использование {107..27..-1}(или, выражаясь короче {107..27}) было бы достаточным для решения вашей проблемы, поскольку при замене 30 были бы найдены только исходные 30, а 27 еще не были заменены.

решение4

Хорошо, я думаю, что у меня есть решение для двойного индекса, а также изменение команды cas. Это делает работу:

perl -p -e 's/\[(\d+)\]\[(\d+)\]/"[" . ($1) . "][" . ($2+40) . "]"/ge' prova.txt

Кстати, не совсем понимаю, зачем мне нужна эта . ($1) .(точка с пробелом).

Связанный контент