GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Mit ein paar kleinen Änderungen ein paar Zeilen in einer Textdatei duplizieren?

Ich versuche herauszufinden, wie man einen einzelnen Zeilenbereich in einer Textdatei repliziert. Der Bereich beginnt mit einer Zeile, die in der Datei eindeutig ist, aber der Bereich endet mit einer Zeile, die an mehreren Stellen in der Datei vorhanden sein kann.

Hier ist eine Beispieleingabe, die ich verarbeiten muss:

I have no imagination
so this sample text will
Common
be boring. But it does
demonstrate the problem
I am trying to solve.
Common
Hi mom!
This is a unique line.
And here is some more
text that should be copied
as well.
Common
Followed by text that should
not be copied.

Die Zeilen, die ich duplizieren und ändern muss, sind fett gedruckt, um sie hier hervorzuheben.

Die Ausgabe, die ich brauche, ist:

I have no imagination
so this sample text will
Common
be boring. But it does
demonstrate the problem
I am trying to solve.
Common
Hi mom!
This is a changed line.
And here is different more
text that should be copied
as well.
Common
This is a unique line.
And here is some more
text that should be copied
as well.
Common
Followed by text that should
not be copied.

Die zusätzliche Ausgabe ist zur Verdeutlichung fett gedruckt.

Ich muss den Zeilenbereich erhalten, der mit der Zeile beginnt:

This is a unique line

und endet mit der Zeile:

Common

Dieser Zeilenbereich muss unmittelbar vor dem ursprünglichen Zeilenbereich eingefügt werden. Die Kopie des übereinstimmenden Zeilenbereichs muss leicht modifiziert werden.

Die „Common“-Zeile, die den Bereich beendet, kann selbst an vielen Stellen innerhalb der Datei vorkommen.

Ich habe mir ein funktionierendes awk ausgedacht Skript, aber es scheint viel komplizierter zu sein, als es sein muss. Mein awk Fähigkeiten sind nicht vorhanden.

/This is a unique line/{flag=1}
/Common/{
    if (flag > 0) {
        n=m;
        sub("some","different",n);
        sub("unique","changed",n);
        print n "\n" $0 "\n" m;
        m=""
    };
    flag=0
};
flag{
    if (length(m) > 0) {
        m=m "\n" $0
    } else {
        m=$0
    }
}
!flag{ print }

Gibt es eine sauberere, weniger ausführliche Möglichkeit, dies zu implementieren? Ich bin offen für andere Optionen außer awk . Es muss nur ein unter macOS verfügbarer Standardbefehl sein.

Akzeptierte Antwort:

awk '/This is a unique line/,/Common/{
   H = H RS $0
   if ( $0 ~ /Common/ ) {
      g = H
      sub("\n","",g)
      sub("some","different",g)
      sub("unique","changed",g)
      $0 = g H
   } else { next }
}1'   inputfile

Hier ist der sed Code (zeigte ich im Antwortabschnitt) übersetzt in awk .

Beachten Sie, dass Sie mit dem Code, den Sie haben, die Verantwortung für das Ein- und Ausschalten von awk übernehmen Variables Flag, um Zeilen zu verfolgen. Aber während awk tut es unter der Haube bereits für Sie, wenn Sie seinen range verwenden Operator ,


Linux
  1. Cat Zeile X bis Zeile Y in einer riesigen Datei?

  2. Wie entferne ich doppelte Zeilen in einer Textdatei?

  3. Zeilenbereich durch Zeilenbereich ersetzen (sed oder andere)?

  4. Ersetzen Sie Linien, die einem Muster entsprechen, durch Linien aus einer anderen Datei in der richtigen Reihenfolge?

  5. Aufeinanderfolgende Zeilen in CSV mit doppelten Werten in einem Feld löschen, aber die letzte Zeile beibehalten?

Diff-Befehl in Linux mit Beispielen

Bearbeiten von Text auf der Kommandozeile mit sed

Bearbeiten von Text in der Befehlszeile mit grep

So finden Sie die längste(n) Zeile(n) in einer Datei in Linux

Suchen und ersetzen Sie Text in einer Datei zwischen einem Zeilenbereich mit sed

Echotext mit neuer Zeile in Bash