Ich möchte der Datei weitere Terminals hinzufügen /etc/securetty
. Genauer gesagt möchte ich hinzufügen pts/n
, wo n
sich im Bereich befindet 0-9
, wenn es nicht existiert. Ist dies per sed
Befehl 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 -p
Option wird autoprint
Zeilen. Wenn wir die erreichen, eof
ziehen wir den Hash heraus %h
und leiten ihn durch den grep
Filter, um zu bestimmen, welche Terminals nicht gedruckt haben, und wir verwenden, map
um 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 space
mit 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 eof
erhalten 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/N
Zeilen 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 ,p
durch „ w
direkt 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-i
um die Datei direkt zu bearbeiten)
Antwort4
sed
verarbeitet 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 grep
herausfinden, ob eine Datei ein bestimmtes Muster enthält; mit -f
kö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"