Чисто подкачайте все происшествия двух строк с помощью sed

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

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

Когда я изучал различие между двумя (и прежде чем это стало второй натурой), я буду всегда помнить, что "короткий" дефис соответствует "коротким" опциям, в то время как "длинное" (или дважды) дефис соответствует "долгим" опциям. Я не знаю, использовалось ли то обоснование в разработке стиля двойного дефиса, но это - возможность.

13
20.09.2011, 00:41
3 ответа

Если StringB и StringA не может появиться на той же входной строке, затем можно сказать sed выполнять замену один путь и только пробовать другой путь, если не было никаких случаев первой искавшей строки.

<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'

В общем случае я не думаю, что в sed существует легкий метод. Между прочим, обратите внимание, что спецификация неоднозначна если StringA и StringB может наложиться. Вот решение для Perl, которое заменяет крайнее левое возникновение любой строки и повторения.

<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
                    s/(StringA|StringB)/$r{$1}/ge'

Если Вы хотите придерживаться инструментов POSIX, awk является способом пойти. Awk не имеет примитива для общих параметрических замен, таким образом, Вам нужно к самокрутке.

<file.txt awk '{
    while (match($0, /StringA|StringB/)) {
        printf "%s", substr($0, 1, RSTART-1);
        $0 = substr($0, RSTART);
        printf "%s", /^StringA/ ? "StringB" : "StringA";
        $0 = substr($0, 1+RLENGTH)
    }
    print
}'
11
27.01.2020, 19:53
  • 1
    Когда я выполняю первую команду, sed говорит мне sed: can't read s/StringB/StringA/g: No such file or directory. Это кажется -e t PATTERN не хорошо понят. –  Gyscos 01.10.2017, 21:16
  • 2
    @Gyscos Там был отсутствием -e перед вторым s команда. Я исправил свой ответ. –  Gilles 'SO- stop being evil' 01.10.2017, 21:49
[113933] Я думаю, что вполне корректно использовать строку "nonce", чтобы поменять два слова. Если вам нужно более общее решение, вы можете сделать что-то вроде:[12136]Это дает [12137]Обратите внимание, что здесь вам нужны две дополнительные замены, чтобы избежать замены [114411]x_x[114412], если у вас случайно есть строки "x_x". Но даже это все равно кажется более простым, чем решение [114413]awk[114414] для меня.[113938].
3
27.01.2020, 19:53

прямо сейчас я делаю что-то вроде
...............
Проблема с этим подходом состоит в том, что она предполагает, что stringc не происходят в файле.

Я думаю, что ваш подход в порядке, вы должны просто использовать что-то еще вместо строки, то, что не может происходить в строке (в пространстве шаблона). Лучший кандидат - это \ N EWLILE.
Обычно входная строка в пространстве шаблона не будет содержать этот символ так, чтобы поменять все вхождения этого и , и в файле, вы можете запустить:

sed 's/THIS/\
/g
s/THAT/THIS/g
s/\n/THAT/g' infile

или, если ваш SED поддерживает \ N в RHS:

sed 's/THIS/\n/g;s/THAT/THIS/g;s/\n/THAT/g' infile
8
27.01.2020, 19:53

Теги

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