Необходимо включить расширенные регулярные выражения для этого:
grep -E ':[[:alnum:]]+:' ~/x.txt
Вы можете просто использовать sed
для исправления:
printf '%s\n' "$i" "$j" |
sed 's/[]\$*&/.^[]/\\&/g;H;$!d
x;y|\n|/|;s|.*|s&/g|' |
sed -f - /path/to/infile
Так что это s///
ubstitution избавится от любого/всех BRE-символов во входных данных:
s/[]\$*&/.^[]/\\&/g
... путем префиксации каждого из них обратной косой чертой. Первый sed
затем сохраняет копию первой строки - $i
- в H
старом месте, префиксовав к ней символ \n
ewline. Строка $i
затем d
поднимается, потому что это !
не последняя $
. Следующая строка - строка $j
- тоже последняя, и после того, как к ней будет применена та же обработка, что и к первой, она будет , а не d
поднята. Вместо этого она ex
меняет буферы удержания и буферы паттерна и работает на конкатенированных результатах. В этой точке пространство паттерна выглядит следующим образом:
\n1\.0\n2\.0
...поэтому мы y///
переводим все \n
ewlines для /
косых черт, s///
ubstitute . *
все шаблоны-пространства для самого и
плюс готовые с
и дополнительный /g
, который получает нас:
s/1\.0/2\.0/g
Это затем автоматически распечатывается на второй sed
, который читает stdin - или -f -
- как свой скрипт. Когда первый sed
заканчивается и закрывает трубу между ними, второй sed
начинает применять...
s/1\.0/2\.0/g
...к каждой строке в его именованном входном файле - который здесь /путь/к/в файле
.
Я написал ваш файл вот так:
printf '%04s%04s%04s%04s\n' \
0 0 -1 0 1 0 0 0 0 -1\
0 0 1.5 2.0 1.0 0 >/tmp/temp
, в результате чего у меня получился файл типа...
0 0 -1 0
1 0 0 0
0 -1 0 0
1.5 2.0 1.0 0
Затем я написал другую версию Вашего скрипта, например:
ii=0.0
for i in 1.0 2.0 3.0 4.0
do str2=$i
printf '\033[41m## %s \033[0m\n' \
"str2 = $str2" "$ii $str2"
printf %s\\n "$ii" "$str2"
ii=$str2
done |
sed ' s/[]\$^&*./[]/\\&/g;H;x
s|^\(\n\)\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)|\
bs\5\1:i\5\1i\\\1\2\\\1\3\1:s\5\1s/\4/\5/gp;ti\5|p
s|||;h;d' |
sed -f - /tmp/temp
Который использует оболочку только для генерации строк, но позволяет sed
выполнять всю обработку данных. Обратите внимание, что хотя два sed
s вызываются каждый, они вызываются только один раз.
Когда я запускаю его, результаты следующие:
0 0 -1 0
1 0 0 0
0 -1 0 0
1.5 2.0 2.0 0
## str2 = 2.0
## 1.0 2.0
1.5 3.0 3.0 0
## str2 = 3.0
## 2.0 3.0
1.5 4.0 4.0 0
## str2 = 4.0
## 3.0 4.0
1.5 4.0 4.0 0
Строки, начинающиеся с #
окрашены в красный цвет, как я и ожидал, что вы имеете в виду. sed
записывает их только тогда, когда успешно завершено восстановление s///
ubstitution. Сценарий, который первый sed
пишет для второго выглядит следующим образом:
bs1\.0
:i1\.0
i\
[41m## str2 = 1\.0 [0m\
[41m## 0\.0 1\.0 [0m
:s1\.0
s/0\.0/1\.0/gp;ti1\.0
bs2\.0
:i2\.0
i\
[41m## str2 = 2\.0 [0m\
[41m## 1\.0 2\.0 [0m
:s2\.0
s/1\.0/2\.0/gp;ti2\.0
bs3\.0
:i3\.0
i\
[41m## str2 = 3\.0 [0m\
[41m## 2\.0 3\.0 [0m
:s3\.0
s/2\.0/3\.0/gp;ti3\.0
bs4\.0
:i4\.0
i\
[41m## str2 = 4\.0 [0m\
[41m## 3\.0 4\.0 [0m
:s4\.0
s/3\.0/4\.0/gp;ti4\.0
Обратите внимание, что хотя строки [
не экранируются, это просто влияние моего терминала на выход - который в результате съедает char сразу после \033
. Когда второй sed
получает скрипт, то входной сигнал подобен \033\[...].
, но его вывод i
nserts to stdout - это \033[...].
Попробуйте:
Избежать всех. заменив все .
к \.
str1="$( echo -n $i | sed 's/\./\\\./g' )"
Повторите одинаковую для STR2, используя $ j . Тогда замените следующим образом
sed "s/$str1/$str2/g"