Suchen Sie die Zeilennummer, die das Muster enthält, mit einem benutzerdefinierten Regex-Trennzeichen

7

Wie im Beispiel versuche ich, Zeilennummern zu erhalten, die das Muster enthalten. Mein Muster enthält Schrägstriche, daher wollte ich ein benutzerdefiniertes Trennzeichen hinzufügen.

Dieser einfache funktioniert:

sed -n '/file/=' temp.txt

Die Verwendung des Trennzeichens für das Ersetzen von Zeichenfolgen funktioniert auch:

sed 's|file|gile|' temp.txt

Aber wenn ich dem ersten Beispiel ein Trennzeichen hinzufügen möchte, funktioniert dies nicht:

sed -n '|file /etc|=' temp.txt

Ich weiß, dass ich Schrägstrichen entkommen kann, aber ich würde es vorziehen, ein benutzerdefiniertes Trennzeichen hinzuzufügen. Irgendeine Idee, wie ich meinen Befehl reparieren kann?

jasiustasiu
quelle
sed -n '\|file /etc|='
Stéphane Chazelas
Vielen Dank! Was ich nach Ihrer Antwort gefunden habe: \% regexp% (Das% kann durch ein anderes einzelnes Zeichen ersetzt werden.) Dies entspricht auch dem regulären Ausdruck regexp, ermöglicht jedoch die Verwendung eines anderen Trennzeichens als /. Dies ist besonders nützlich, wenn der reguläre Ausdruck selbst viele Schrägstriche enthält, da er das mühsame Entweichen jedes / vermeidet. Wenn der reguläre Ausdruck selbst Trennzeichen enthält, muss jedes durch einen Backslash () maskiert werden.
jasiustasiu
Verwandte: askubuntu.com/questions/77156/how-to-get-line-number-from-grep
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功

Antworten:

9

Stéphane gab Ihnen die sedLösung:

sed -n  '\|file /etc|=' file 

Wenn Sie bereit sind, andere Tools zu verwenden, können Sie dies auch tun

grep -n 'file /etc' file

Dadurch wird auch die Zeile selbst gedruckt. Um die Zeilennummer allein zu erhalten, versuchen Sie Folgendes:

grep -n 'file /etc' file | cut -d: -f 1

Oder Sie können verwenden perl:

perl -lne 'm|file /etc| && print $.' file 

Oder awk:

awk '$0 ~ "file /etc" {print NR}'
terdon
quelle
Wenn Sie den Punkt verwenden, wird "etc" vor einem beliebigen Zeichen angezeigt. Verwenden Sie einen Schrägstrich, um genau zu sein.
Bis auf weiteres angehalten.
@ TennisWilliamson Ich habe keine Ahnung, warum ich in einigen davon einen Punkt verwendet habe. Muss ein Artefakt aus meinen Testläufen gewesen sein. Danke, behoben.
Terdon
4

In allen Kontextadressen müssen Sie das öffnende Trennzeichen umgehen, es sei denn, Sie verwenden die Standardeinstellung /. Alle folgenden Vorkommen, die maskiert werden, werden als Literalzeichen und nicht als Endbegrenzer behandelt.

  • Standardtrennzeichen:

    /start/,/end/{/pattern/d;}
    
  • benutzerdefiniertes Trennzeichen:

    \#start#,\#end#{\#pattern#d;}
    

Siehe die POSIX-Dokumente :

In einer Kontextadresse ist die Konstruktion \ cREc, in der c ein anderes Zeichen als ein Backslash- oder Newline-Zeichen ist, identisch mit / RE / Wenn das mit c bezeichnete Zeichen nach einem Backslash erscheint, wird es als das Literalzeichen betrachtet, das beendet den RE nicht. In der Kontextadresse \ xabc \ xdefx steht beispielsweise das zweite x für sich selbst, sodass der reguläre Ausdruck abcxdef lautet.

Ähnliche Beschreibung auf der GNU- sed manSeite:

/regexp/
       Match lines matching the regular expression regexp.      
\cregexpc
       Match lines matching the regular expression regexp.  
       The c may be any character.

und FreeBSD sed manSeite:

In a context address, any character other than a backslash (``\'')
or newline character may be used to delimit the regular expression.
The opening delimiter   needs to be preceded by a backslash unless it
is a slash.  For example, the   context address \xabcx is equivalent
to /abc/.  Also, putting a backslash character before   the delimiting
character within the regular expression causes the character to be
treated literally.  For example, in the context address \xabc\xdefx,
the RE delimiter is an ``x'' and the second ``x'' stands for itself,
so that the regular expression is ``abcxdef''.
don_crissti
quelle