Используйте sed, чтобы использовать & ldquo; найти и заменить & rdquo; для каждого второго случая

У меня есть папка с +1000 .dat файлами. И каждый файл содержит много строк следующего типа:

-0.0999999999999659-0.0000000006287859 -0.08999999999997500.8000000006183942 -0.0799999999999841-0.0000000007463807 -0.06999999999999320.0000000008661516 -0.06000000000000230.0000000008640644 -0.05000000000001140.0000000008807621 -0.0400000000000205-0.7000000009575896 -0.02999999999997270.0000000009476864 -0.01999999999998180.0000000009150902 -0.00999999999999090.0000000008144152 0.00000000000000000.0000000007097434 0.00999999999999090.0000000007847500 0.01999999999998180.0000000009030998 0.03000000000002960.0000000009741985

Для всех файлов, которые я хочу преобразовать в

-0.0999999999999659 -0.0000000006287859 -0.0899999999999750 0.8000000006183942 -0.0799999999999841 -0.0000000007463807 -0.0699999999999932 0.0000000008661516 -0.0600000000000023 0.0000000008640644 -0.0500000000000114 0.0000000008807621 -0.0400000000000205 -0.7000000009575896 -0.0299999999999727 0.0000000009476864 -0.0199999999999818 0.0000000009150902 -0.0099999999999909 0.0000000008144152 0.0000000000000000 0.0000000007097434 0.0099999999999909 0.0000000007847500 0.0199999999999818 0.0000000009030998 0.0300000000000296 0.0000000009741985

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

Поэтому я подумал об использовании «найти и заменить» только для второй «точки» следующим образом. Найти:

0.

Заменить на:

0.

Я не знаю, как указать sed, чтобы действовать только на «вторую точку» на каждой строке. У кого-нибудь есть хорошая идея о том, как это сделать?

4
задан 14 May 2017 в 21:25

12 ответов

 sed -E s'/(.*[^-])(-?0\.)/\1    \2/' 999.dat

* жадный и съедает как можно больше символов, так что \. всегда совпадает с последней строкой. [F4] гарантирует, что дополнительный - второго номера попадает во вторую группу.

5
ответ дан 22 May 2018 в 22:39
  • 1
    Он работает с: find / home / folder -name * .dat -exec sed -i -E s '/(.*[^-])(-? 0 \.) / \ 1 \ 2 /' {} \ ; Большое вам спасибо, вы спасли мне много работы! – Hunter 14 May 2017 в 01:54
sed -E s'/(.*[^-])(-?0\.)/\1 \2/' 999.dat

* жадный и съедает как можно больше символов, так что \. всегда совпадает с последней строкой. [F4] гарантирует, что дополнительный - второго номера попадает во вторую группу.

5
ответ дан 18 July 2018 в 13:21
sed -E s'/(.*[^-])(-?0\.)/\1 \2/' 999.dat

* жадный и съедает как можно больше символов, так что \. всегда совпадает с последней строкой. [F4] гарантирует, что дополнительный - второго номера попадает во вторую группу.

5
ответ дан 24 July 2018 в 20:09

Чтобы заменить только второе вхождение, используйте модификатор 2. Таким образом:

$ sed -E 's/-?[[:digit:]][.]/    &/2' file.dat
-0.0999999999999659    -0.0000000006287859
-0.0899999999999750    0.8000000006183942
-0.0799999999999841    -0.0000000007463807
-0.0699999999999932    0.0000000008661516
-0.0600000000000023    0.0000000008640644
-0.0500000000000114    0.0000000008807621
-0.0400000000000205    -0.7000000009575896
-0.0299999999999727    0.0000000009476864
-0.0199999999999818    0.0000000009150902
-0.0099999999999909    0.0000000008144152
0.0000000000000000    0.0000000007097434
0.0099999999999909    0.0000000007847500
0.0199999999999818    0.0000000009030998
0.0300000000000296    0.0000000009741985

Как это работает:

-E Это говорит sed использовать расширенное регулярное выражение. Это устраняет необходимость выхода из режима ?. s/-?[[:digit:]][.]/ &/2 Это ищет необязательный -, за которым следует цифра, за которой следует буква .. В заменяющем тексте четыре пробела добавляются до того, как будет соответствовать соответствующая строка, обозначенная &. Модификатор 2 в конце подстановочной команды сообщает sed только заменить второе вхождение шаблона.

Связанные примеры

Несколько примеров, показывающих, как могут быть сделаны различные подстановки:

$ echo aaaa | sed 's/a/A/1'
Aaaa
$ echo aaaa | sed 's/a/A/2'
aAaa
$ echo aaaa | sed 's/a/A/3'
aaAa
$ echo aaaa | sed 's/a/A/4'
aaaA
$ echo aaaa | sed 's/a/A/g'
AAAA
5
ответ дан 22 May 2018 в 22:39
  • 1
    Спасибо за ответ! Я не уверен, почему, но ваше решение не работает для меня. Я использовал следующий синтаксис: find / home / folder -name * .dat -exec sed -i -E s '/(.*[^-])(-? 0 \.) / \ 1 \ 2 /' {} \ ;. Хотя он работает для некоторых строк, он пропускает многие другие строки. – Hunter 14 May 2017 в 01:57
  • 2
    Решение, которое вы упомянули, sed -i -E s'/(.*[^-])(-?0\.)/\1 \2/', - это не мое решение. Мне кажется, что вы имеете в виду решение @ FlorianDiesch. – John1024 14 May 2017 в 02:15
  • 3
    Извините, я имел в виду, что я использовал: find / home / folder -name * .dat -exec sed -i -E 's / -? 0 [.] / (Four_spaces) & amp; / 2' {} \ ;, но это не работает для многих линий. Не знаю, почему, я не мог найти в ней никакой картины. – Hunter 14 May 2017 в 03:10
  • 4
    @Hunter Если вы можете показать мне несколько строк, на которых это не сработало, мне было бы интересно. – John1024 14 May 2017 в 03:31
  • 5
    Я проверил его с find /home/folder -name \*.dat -exec sed -i -E 's/-?[[:digit:]][.]/ &/2' {} \;, и он действительно работает сейчас! +1 и еще раз спасибо! – Hunter 14 May 2017 в 21:21

найти первую точку:)

sed -r 's/(.*\.[^-\.]*)(-?)0\.(.*)/\1\t\20.\3/' file

Примечания

-r использовать ERE s/old/new заменить old на new (some chars) сохранить some chars ссылаться на .* любое число любых символов \. literal . [^-\.] любых символов, кроме дефиса или . -? необязательно - \1\t\20.\3 печатать сохраненные шаблоны, вкладку и 0. ] в правильных местах
2
ответ дан 22 May 2018 в 22:39

Как насчет

$ sed -E 's/(-?0\.[0-9]+)(-?0\.[0-9]+)/\1\t\2/' file
-0.0999999999999659     -0.0000000006287859
-0.0899999999999750     0.8000000006183942
-0.0799999999999841     -0.0000000007463807
-0.0699999999999932     0.0000000008661516
-0.0600000000000023     0.0000000008640644
-0.0500000000000114     0.0000000008807621
-0.0400000000000205     -0.7000000009575896
-0.0299999999999727     0.0000000009476864
-0.0199999999999818     0.0000000009150902
-0.0099999999999909     0.0000000008144152
0.0000000000000000      0.0000000007097434
0.0099999999999909      0.0000000007847500
0.0199999999999818      0.0000000009030998
0.0300000000000296      0.0000000009741985

Как это работает:

-?0\.[0-9]+ соответствует 0., за которым следует одна или несколько других десятичных цифр и необязательно предшествующая - (-?0\.[0-9]+)(-?0\.[0-9]+) захватить 2 экземпляра выше \1\t\2 заменить их обратно TAB между
2
ответ дан 22 May 2018 в 22:39

Чтобы заменить только второе вхождение, используйте модификатор 2. Таким образом:

$ sed -E 's/-?[[:digit:]][.]/ &/2' file.dat -0.0999999999999659 -0.0000000006287859 -0.0899999999999750 0.8000000006183942 -0.0799999999999841 -0.0000000007463807 -0.0699999999999932 0.0000000008661516 -0.0600000000000023 0.0000000008640644 -0.0500000000000114 0.0000000008807621 -0.0400000000000205 -0.7000000009575896 -0.0299999999999727 0.0000000009476864 -0.0199999999999818 0.0000000009150902 -0.0099999999999909 0.0000000008144152 0.0000000000000000 0.0000000007097434 0.0099999999999909 0.0000000007847500 0.0199999999999818 0.0000000009030998 0.0300000000000296 0.0000000009741985

Как это работает:

-E Это говорит sed использовать расширенное регулярное выражение. Это устраняет необходимость выхода из режима ?. s/-?[[:digit:]][.]/ &/2 Это ищет необязательный -, за которым следует цифра, за которой следует буква .. В заменяющем тексте четыре пробела добавляются до того, как будет соответствовать соответствующая строка, обозначенная &. Модификатор 2 в конце подстановочной команды сообщает sed только заменить второе вхождение шаблона.

Связанные примеры

Несколько примеров, показывающих, как могут быть сделаны различные подстановки:

$ echo aaaa | sed 's/a/A/1' Aaaa $ echo aaaa | sed 's/a/A/2' aAaa $ echo aaaa | sed 's/a/A/3' aaAa $ echo aaaa | sed 's/a/A/4' aaaA $ echo aaaa | sed 's/a/A/g' AAAA
5
ответ дан 18 July 2018 в 13:21

Как насчет

$ sed -E 's/(-?0\.[0-9]+)(-?0\.[0-9]+)/\1\t\2/' file -0.0999999999999659 -0.0000000006287859 -0.0899999999999750 0.8000000006183942 -0.0799999999999841 -0.0000000007463807 -0.0699999999999932 0.0000000008661516 -0.0600000000000023 0.0000000008640644 -0.0500000000000114 0.0000000008807621 -0.0400000000000205 -0.7000000009575896 -0.0299999999999727 0.0000000009476864 -0.0199999999999818 0.0000000009150902 -0.0099999999999909 0.0000000008144152 0.0000000000000000 0.0000000007097434 0.0099999999999909 0.0000000007847500 0.0199999999999818 0.0000000009030998 0.0300000000000296 0.0000000009741985

Как это работает:

-?0\.[0-9]+ соответствует 0., за которым следует одна или несколько других десятичных цифр и необязательно предшествующая - (-?0\.[0-9]+)(-?0\.[0-9]+) захватить 2 экземпляра выше \1\t\2 заменить их обратно TAB между
2
ответ дан 18 July 2018 в 13:21

найти первую точку:)

sed -r 's/(.*\.[^-\.]*)(-?)0\.(.*)/\1\t\20.\3/' file

Примечания

-r использовать ERE s/old/new заменить old на new (some chars) сохранить some chars ссылаться на .* любое число любых символов \. literal . [^-\.] любых символов, кроме дефиса или . -? необязательно - \1\t\20.\3 печатать сохраненные шаблоны, вкладку и 0. ] в правильных местах
2
ответ дан 18 July 2018 в 13:21

Чтобы заменить только второе вхождение, используйте модификатор 2. Таким образом:

$ sed -E 's/-?[[:digit:]][.]/ &/2' file.dat -0.0999999999999659 -0.0000000006287859 -0.0899999999999750 0.8000000006183942 -0.0799999999999841 -0.0000000007463807 -0.0699999999999932 0.0000000008661516 -0.0600000000000023 0.0000000008640644 -0.0500000000000114 0.0000000008807621 -0.0400000000000205 -0.7000000009575896 -0.0299999999999727 0.0000000009476864 -0.0199999999999818 0.0000000009150902 -0.0099999999999909 0.0000000008144152 0.0000000000000000 0.0000000007097434 0.0099999999999909 0.0000000007847500 0.0199999999999818 0.0000000009030998 0.0300000000000296 0.0000000009741985

Как это работает:

-E Это говорит sed использовать расширенное регулярное выражение. Это устраняет необходимость выхода из режима ?. s/-?[[:digit:]][.]/ &/2 Это ищет необязательный -, за которым следует цифра, за которой следует буква .. В заменяющем тексте четыре пробела добавляются до того, как будет соответствовать соответствующая строка, обозначенная &. Модификатор 2 в конце подстановочной команды сообщает sed только заменить второе вхождение шаблона.

Связанные примеры

Несколько примеров, показывающих, как могут быть сделаны различные подстановки:

$ echo aaaa | sed 's/a/A/1' Aaaa $ echo aaaa | sed 's/a/A/2' aAaa $ echo aaaa | sed 's/a/A/3' aaAa $ echo aaaa | sed 's/a/A/4' aaaA $ echo aaaa | sed 's/a/A/g' AAAA
5
ответ дан 24 July 2018 в 20:09
  • 1
    Спасибо за ответ! Я не уверен, почему, но ваше решение не работает для меня. Я использовал следующий синтаксис: find / home / folder -name * .dat -exec sed -i -E s '/(.*[^-])(-? 0 \.) / \ 1 \ 2 /' {} \ ;. Хотя он работает для некоторых строк, он пропускает многие другие строки. – Hunter 14 May 2017 в 01:57
  • 2
    Решение, которое вы упомянули, sed -i -E s'/(.*[^-])(-?0\.)/\1 \2/', - это не мое решение. Мне кажется, что вы имеете в виду решение @ FlorianDiesch. – John1024 14 May 2017 в 02:15
  • 3
    Извините, я имел в виду, что я использовал: find / home / folder -name * .dat -exec sed -i -E 's / -? 0 [.] / (Four_spaces) & amp; / 2' {} \ ;, но это не работает для многих линий. Не знаю, почему, я не мог найти в ней никакой картины. – Hunter 14 May 2017 в 03:10
  • 4
    @Hunter Если вы можете показать мне несколько строк, на которых это не сработало, мне было бы интересно. – John1024 14 May 2017 в 03:31
  • 5
    Я проверил его с find /home/folder -name \*.dat -exec sed -i -E 's/-?[[:digit:]][.]/ &/2' {} \;, и он действительно работает сейчас! +1 и еще раз спасибо! – Hunter 14 May 2017 в 21:21

Как насчет

$ sed -E 's/(-?0\.[0-9]+)(-?0\.[0-9]+)/\1\t\2/' file -0.0999999999999659 -0.0000000006287859 -0.0899999999999750 0.8000000006183942 -0.0799999999999841 -0.0000000007463807 -0.0699999999999932 0.0000000008661516 -0.0600000000000023 0.0000000008640644 -0.0500000000000114 0.0000000008807621 -0.0400000000000205 -0.7000000009575896 -0.0299999999999727 0.0000000009476864 -0.0199999999999818 0.0000000009150902 -0.0099999999999909 0.0000000008144152 0.0000000000000000 0.0000000007097434 0.0099999999999909 0.0000000007847500 0.0199999999999818 0.0000000009030998 0.0300000000000296 0.0000000009741985

Как это работает:

-?0\.[0-9]+ соответствует 0., за которым следует одна или несколько других десятичных цифр и необязательно предшествующая - (-?0\.[0-9]+)(-?0\.[0-9]+) захватить 2 экземпляра выше \1\t\2 заменить их обратно TAB между
2
ответ дан 24 July 2018 в 20:09

найти первую точку:)

sed -r 's/(.*\.[^-\.]*)(-?)0\.(.*)/\1\t\20.\3/' file

Примечания

-r использовать ERE s/old/new заменить old на new (some chars) сохранить some chars ссылаться на .* любое число любых символов \. literal . [^-\.] любых символов, кроме дефиса или . -? необязательно - \1\t\20.\3 печатать сохраненные шаблоны, вкладку и 0. ] в правильных местах
2
ответ дан 24 July 2018 в 20:09

Другие вопросы по тегам:

Похожие вопросы: