первая замена строки в файле с помощью sed - PullRequest
5 голосов
/ 21 апреля 2011

Хотелось бы узнать, как заменить первое вхождение искомого шаблона во всем файле. Например,

import java.io.File;
import java.io.File;

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

import java.io.IOException;
import java.io.File;

Как мне добиться этого с помощью sed? Спасибо

Ответы [ 5 ]

2 голосов
/ 27 мая 2011
cat file | sed -e ':l
    0,/my_search_str/ {
    /my_search_str/! {
            N;
            b l
            }
    s/my_search_str/replace_this/g  
    :t
    N
    b t     
    }
    '

это работает для меня: файл: (до)

hello1
my_search_str
hello2
mysearch_str
hello3

файл: (после)

hello1
replace_this
hello2
mysearch_str
hello3
2 голосов
/ 22 апреля 2011

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

Вот Perl с одним вкладышем:

% cat -n /tmp/f
     1  import java.lang.Character;
     2  import java.io.File;
     3  import java.io.File;
     4  import java.util.Pattern;

% perl -pe 's//IoException/ if m?import java\.io\.\KFile?' /tmp/f
import java.lang.Character;
import java.io.IoException;
import java.io.File;
import java.util.Pattern;

И если вы хотите сделать это с редактированием файла, просто добавьте -i.bak :

% perl -i.bak -pe 's//IoException/ if m?import java\.io\.\KFile?' /tmp/f

% head /tmp/f{,.bak}
==> /tmp/f <==
import java.lang.Character;
import java.io.IoException;
import java.io.File;
import java.util.Pattern;

==> /tmp/f.bak <==
import java.lang.Character;
import java.io.File;
import java.io.File;
import java.util.Pattern;

Причина, по которой это работает, заключается в том, что когда вы задаете для оператора m// разделитель ??, он имеет некоторое встроенное состояние, которое нужно запомнить, чтобы соответствовать только в первый раз.

Тогда в замене пустой шаблон означает повторное использование последнего сопоставленного шаблона, так что вам не придется вводить его снова и рисковать тем, что они когда-либо будут отклоняться.

Наконец, \K в шаблоне отступает от матча, «удерживая» материал слева, чтобы он не сожрал заменитель.

1 голос
/ 27 мая 2011

Что я хотел бы сделать, это добавить все строки в большую строку и заменить содержимое.

$ cat f
import java.io.File;
import java.io.File;
$ sed -n 'N
  ${
    s/import java.io.File;/import java.io.IOException/
    p
  }' f
import java.io.IOException
import java.io.File;

Как это работает: во-первых, я подавляю печать строк, что является поведением по умолчанию, передавая параметр -n в sed.

Затем идут команды sed. Первая - это команда N: она добавляет новую строку и следующую строку потока к текущей, сохраняя ее в пространстве шаблона. Это изменит текущую строку на следующую, а затем будет добавлена ​​следующая строка ... до конца файла.

В конце файла и после команды N, которая будет выполняться и в последней строке, пространство шаблона будет содержать все строки. Затем в конце файла (который указан адресом $) мы просто заменим нужную строку на:

s/import java.io.File;/import java.io.IOException/

Поскольку команда s/// по умолчанию выполняет только одну замену на итерацию в пространстве шаблона, она заменит только первую строку. Теперь пространство образца заменено линией, но не будет распечатано, так как мы использовали опцию -n. Итак, нам нужно распечатать его с помощью команды p. Как только мы выполним две операции в конце файла, мы обращаемся к нему с помощью $ и помещаем операции в скобки ({}).

Там мы просто представили команды sed в нескольких строках для ясности. Мы можем использовать их все в одной строке; просто разделите их точкой с запятой:

$ sed -n 'N;${s/import java.io.File;/import java.io.IOException/;p;}' f
import java.io.IOException
import java.io.File;

НТН

0 голосов
/ 21 апреля 2011

Просто сделайте это в командной строке, как показано ниже:

cat text.txt |
awk '/File/{
  if ( count < 1 ){ gsub("File","IOException")}
  count++
  print
  }'
0 голосов
/ 21 апреля 2011

Вы можете использовать сценарий оболочки (Bash)

#!/bin/bash

declare -i toggle=0
while read -r line
do
        case "$line" in
            *import*java.io.File*)
            if [ $toggle -eq 1 ];then
                echo "$line"
                continue
            fi
            echo "import java.io.Exception";
            toggle=1
            continue
            ;;
        esac
        echo "$line"
done < file

Пример вывода

$> more file
import java.util.Scanner;
import java.io.File;
import java.io.File;

$> bash search_replace.sh
import java.util.Scanner;
import java.io.Exception
import java.io.File;

Или вы можете вылить весь файл в память и выполнить однократную замену

data=$(<file)
echo "${data/import java.io.File;/import java.io.IOException}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...