4 Stimmen

Alle übereinstimmenden Teilstrings in der Bash extrahieren

Suche nach einer Lösung in Bash (wird Teil eines größeren Skripts sein).

Bei einer Variablen, die Informationen der Form

diff -r efb93662e8a7 -r 53784895c0f7 diff.txt
--- diff.txt Fri Jan 23 14:48:30 2009 +0000
+++ b/diff.txt Fri Jan 23 14:49:58 2009 +0000
@@ -1,9 +0,0 @@ 
-diff -r 9741ec300459 myfile.c 
---- myfile.c Thu Aug 21 18:22:17 2008 +0000 
-+++ b/myfile.c Thu Aug 21 18:22:17 2008 +0000 -@@ -1,4 +1,4 @@ 
-  int myfunc() 
-  { 
--     return 1; 
-+     return 10; 
-  }

Ich möchte beide (hier diff.txt und myfile.c, aber zukünftige Fälle werden nicht auf diese Anzahl beschränkt sein) Dateinamen in einen String der Form "edited: filename1 filename2 ... filenameN" extrahieren.

Zur Verdeutlichung: Ich möchte mehrere übereinstimmende Dateinamen in eine Zeichenfolge extrahieren.

  • Der Befehl "$(expr "$editing" : '.*---[[:space:]]\([[:graph:]]*\)[[:space:]]')" gibt den letzten Dateinamen korrekt zurück, aber nicht die vorherigen Instanzen.

EDIT: Erforderlich ist die Fähigkeit, bearbeitete Dateinamen zu identifizieren (möglicherweise einschließlich Leerzeichen), d.h. Dateinamen, die nach "---" und vor dem Tag "Fr/Do..." erscheinen.

Vielen Dank für Ihre Hilfe (und an die vielen anderen, die bisher geantwortet haben).

3voto

Colas Nahaboo Punkte 749

Eine Lösung, die nur Bash-Build-Ins und keine externen Programme verwendet, ist:

res="edited: "; var="${var#* --- } --- "
while test -n "$var";do res="$res ${var%% *}"; var="${var#* --- }";done
echo "$res"

Er durchläuft alle Vorkommen von " --- ". Der Trick besteht darin, die Zeichenkette vorzubereiten, indem man zuerst den Anfang von "garbarge" abschneidet (bis zum ersten ---) und am Ende ein " --- " anhängt, um anschließend eine einfachere Logik in der while-Schleife zu haben.

Dies geschieht durch die Verwendung der nützlichsten Funktion der Bash, dem # und % zum Trimmen von Zeichenketten

1voto

David Z Punkte 121773

Ich würde vorschlagen, ein externes Tool dafür zu verwenden - hier ist eine Möglichkeit mit Perl:

$(echo "$variable" | perl -e 'print "edited:"; while (<>) { while (/--- (\S+)/g) { print " $1"; } }')

Ich bin mir sicher, dass man das eleganter machen kann, aber ich kann mir im Moment keinen Weg vorstellen, der nicht ein umfangreicheres Programm erfordern würde.

1voto

user50264 Punkte 535

Hier ist eine einfache, funktionierende Lösung:

txt=$(cat)
str="edited: "

for word in $txt; do
        if echo $word | grep -qi '^[a-z0-9-_]*\.[a-z]*$'; then
           str="$str $word"
        fi
done

echo $str

Es läuft:

anton@CAPTAIN-FALCON ~/Desktop
$ bash sol.sh
diff -r efb93662e8a7 -r 53784895c0f7 diff.txt --- diff.txt Fri Jan 23 14:48:30 2
009 +0000 +++ b/diff.txt Fri Jan 23 14:49:58 2009 +0000 @@ -1,9 +0,0 @@ -diff -r
 9741ec300459 myfile.c ---- myfile.c Thu Aug 21 18:22:17 2008 +0000 -+++ b/myfil
e.c Thu Aug 21 18:22:17 2008 +0000 -@@ -1,4 +1,4 @@ - int myfunc() - { -- return
 1; -+ return 10; - }
edited: diff.txt diff.txt myfile.c myfile.c

Editar : Das Herumspielen mit grep führte zu folgendem Skript, aber ich beginne mich zu fragen, ob reine bash das richtige Werkzeug für diese Aufgabe ist... Es scheint, als gäbe es viele Eckfälle, bei denen man entweder einige Dateien übersehen oder falsche Dateinamen erhalten würde.

#! /bin/bash

rawFiles=`cat | grep -ioz ' -* [a-z0-9-_\ ]*\.[a-z]*'`

for file in $rawFiles; do
   if ! echo $file | grep -q '^-*$'; then
      files="$files${file} "
   fi
done

echo "edited: $files"

0voto

Douglas Leeder Punkte 50423

Könnten Sie Ihre Operation durchführen, bevor Sie $editing setzen - dann könnten Sie immer noch die Zeilenumbrüche haben?

Dann könnte man vielleicht mit sed die Dateinamen extrahieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X