Verwenden Sie den Befehl sed, um zu prüfen, ob eine bestimmte Zeile vorhanden ist. Wenn nicht, fügen Sie sie hinzu

Verwenden Sie den Befehl sed, um zu prüfen, ob eine bestimmte Zeile vorhanden ist. Wenn nicht, fügen Sie sie hinzu

Ich möchte der Datei weitere Terminals hinzufügen /etc/securetty. Genauer gesagt möchte ich hinzufügen pts/n, wo nsich im Bereich befindet 0-9, wenn es nicht existiert. Ist dies per sedBefehl möglich? So sieht der Inhalt meiner Datei aus /etc/securetty:

# Local X displays (allows empty passwords with pam_unix's nullok_secure)
pts/0
pts/1
pts/2
pts/3

Ich habe so etwas versucht wie:

sudo sed '+pts/3+a pts/4' /etc/securetty

was den folgenden Fehler erzeugt:

sed: -e expression #1, char 3: extra characters after command

Antwort1

Wir notieren die Punkte/Nummer, wenn wir auf die entsprechende Zeile stoßen. Die -pOption wird autoprintZeilen. Wenn wir die erreichen, eofziehen wir den Hash heraus %hund leiten ihn durch den grepFilter, um zu bestimmen, welche Terminals nicht gedruckt haben, und wir verwenden, mapum das Format dafür vorzubereiten.

perl -lpe 'm|^pts/([0-9])$| and $h{$1}++;
   END{ print for map { "pts/$_" } grep { !$h{$_} } 0 .. 9; }
' /etc/securetty

Wir initialisieren die hold spacemit den Zahlen 0 1 2 ... 9. Immer wenn wir auf die pts/[0-9]Zeile stoßen, schneiden wir diese aus dem Hold Space ab. Bei eoferhalten wir Hold Space und wenn Zahlen gefunden werden, werden diese in das richtige Format gebracht und ausgedruckt.

sed -e '
   # initialize the hold space with 0 1 ... 9
   1{x;s|.*|'"$(echo {0..9})"'|;x}

   # whatever be the line, it needs to be printed
   p

   # we meet a valid pts/ line
   \|^pts/[0-9]$|{
      # the hold space gets appended to the pattern space
      G
      # grab what is the pts number and search for it in the hold and
      # delete itand store back the changes into hold space.
      s|^pts/\([0-9]\)\n\(.*\)\1 |\2|;h
   }

   # weve not arrived at the eof and weve processed the input so go no further
   $!d

   # we are at the eof, so we bring back the hold space. just in case all
   # numbers were dealt with up, we simply bail out. Else, prepend the str 
   # pts/ to the numbers present and simply were home
   g;/[0-9]/!d;s/ //g
   s|[0-9]|pts/&\n|g;s/.$//

   # *TIP*: Sprinkle the l, list pattern space at various places to see 
   # whats going on.

' /etc/securetty 

Antwort2

Wenn eine einzelne Zeile fehlt, können Sie sie hinzufügen, indem Sie jedes Vorkommen entfernen und am Ende anhängen:

sed -n '/pattern/!p;$a pattern'

Es ist allerdings unangenehm, das für 10 Muster zu wiederholen.

sed '/pts\/[0-9]/d;$a pts/0 ...

schlägt fehl, wenn die letzte Zeile entfernt werden soll. Umgekehrt, vorausgesetzt, die erste Zeile ist die einzige, die mit beginnt #:

sed '/#/a pts/0\
pts/1\
pts/2\
pts/3\
pts/4\
pts/5\
pts/6\
pts/7\
pts/8\
pts\9
/pts\/[0-9]/d'

Fies. Ich schlage vor, in diesem Fall ein anderes Werkzeug zu verwenden.

Antwort3

Entfernen Sie einige/alle pts/NZeilen und fügen Sie sie dann alle wieder hinzu:

{ grep -xv '^pts/[0-9]$' /etc/securetty; printf 'pts/%d\n' {0..9}; } > /etc/securetty.new
cat /etc/securetty.new
mv /etc/securetty.new /etc/securetty

Sie können dies auch in einem Rutsch mit Ihrem bevorzugten Textverarbeitungsprogramm erledigen, z. B.ed

ed -s /etc/securetty <<IN
g/^pts\/[0-9]$/d
.r ! printf pts/\%d\\\n {0..9}
,p
q
IN

(ersetzen ,pdurch „ wdirekt bearbeiten“) odersed

{ printf '%s\\\n' '$a' pts/{0..8}
printf '%s\n' 'pts/9' '/^pts\/[0-9]$/d'
} | sed -f- /etc/securetty

was so ziemlich dasselbe ist wie normales

sed '$a\
pts/0\
pts/1\
pts/2\
pts/3\
pts/4\
pts/5\
pts/6\
pts/7\
pts/8\
pts/9
/^pts\/[0-9]$/d' /etc/securetty

(verwendensed mit-ium die Datei direkt zu bearbeiten)

Antwort4

sedverarbeitet die Datei Zeile für Zeile und es ist sehr schwierig, dafür zu sorgen, dass sich Informationen über mehrere Zeilen hinweg „merken“.

Mit können Sie grepherausfinden, ob eine Datei ein bestimmtes Muster enthält; mit -fkönnen Sie mehrere Muster gleichzeitig angeben. Folgendes generiert die vollständige Liste pts/0.. pts/9, entfernt dann die bereits in der angegebenen Datei vorhandenen Muster und fügt die verbleibenden in die Datei ein:

#!/bin/bash
printf 'pts/%d\n' {0..9} \
| grep -vFf "$1"  - >> "$1".new
mv "$1".new "$1"

verwandte Informationen