Frage

Ich bin der Umgang mit einem bestimmten Dateinamen und Notwendigkeit, Informationen von ihnen zu extrahieren.

Die Struktur des Dateinamens ist ähnlich: "20100613_M4_28007834.005_F_RANDOMSTR.raw.gz"

mit RandomStr eine Kette von max 22 Zeichen, und die eine Teilkette (oder nicht) mit dem Format enthalten können „-W [0-9]. [0-9] {2}. [0-9] {3 }“. Dieses substring hat auch die einzigartige Eigenschaft, die mit „-W“.

Die Informationen, die ich zu extrahieren muß, ist der Teil von RandomStr ohne diese optionale Teilkette.

Ich möchte dies in einem Bash-Skript implementieren und so weit die beste Option, ich fand, ist gaffen mit einem regulären Ausdruck zu verwenden. Mein bester Versuch bisher versagt:

gawk --re-interval '{match ($0,"([0-9]{8})_(M[0-9])_([0-9]{8}\\.[0-9]{3})_(.)_(.*)(-W.*)?.raw.gz",arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz"
OTHER-STRING-W0.40+045

Die erwarteten Ergebnisse sind:

gawk --re-interval '{match ($0,$regexp,arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_SOME-STRING.raw.gz"
SOME-STRING
gawk --re-interval '{match ($0,$regexp,arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz"
OTHER-STRING

Wie kann ich den gewünschten Effekt erzielen.

Danke.

War es hilfreich?

Lösung

Sie müssen in der Lage sein Blick Arounds zu verwenden, und ich glaube nicht, awk / gawk unterstützt das, aber grep -P der Fall ist.

$ pat='(?<=[0-9]{8}_M[0-9]_[0-9]{8}\.[0-9]{3}_._)(.*?)(?=(-W.*)?\.raw\.gz)'
$ echo "20100613_M4_28007834.005_F_SOME-STRING.raw.gz" | grep -Po "$pat"
SOME-STRING
$ echo "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz" | grep -Po "$pat"
OTHER-STRING

Andere Tipps

Während die grep Lösung wirklich sehr schön ist, hat der OP kein Betriebssystem erwähnen, und die -P Option scheint nur unter Linux zur Verfügung zu stehen. Es ist auch ziemlich einfach dieses in awk zu tun.

$ awk -F_ '{sub(/(-W[0-9].[0-9]+.[0-9]+)?\.raw\.gz$/,"",$NF); print $NF}' <<EOT
> 20100613_M4_28007834.005_F_SOME-STRING.raw.gz
> 20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz
> EOT
SOME-STRING
OTHER-STRING
$ 

Beachten Sie, dass dieser bricht auf "20100613_M4_28007834.005_F_OTHER-STRING-W0_40 + 045.raw.gz". Wenn dies ein Risiko ist, und -W zeigt nur oben an der Stelle nach oben gezeigt, könnte es sein, besser zu nutzen so etwas wie:

$ awk -F_ '{sub(/(-W[0-9.+]+)?\.raw\.gz$/,"",$NF); print $NF}'

Die Schwierigkeit scheint die Tatsache zu sein, dass die (.*) vor dem optionalen (-W.*)? verschlingt letztere Text auf. ein nicht gieriges Spiel unter Verwendung von nicht hilft auch nicht. Mein regex-fu leider zu schwach ist, um diese zu bekämpfen.

Wenn Sie nicht eine Multi-Pass-Lösung nichts dagegen haben, dann ist ein einfacher Ansatz zur ersten sanitize der Eingang würde durch die hinteren .raw.gz und mögliche -W* entfernen.

str="20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz"
echo ${str%.raw.gz}  | # remove trailing .raw.gz
     sed 's/-W.*$//' | # remove trainling -W.*, if any
     sed -nr 's/[0-9]{8}_M[0-9]_[0-9]{8}\.[0-9]{3}_._(.*)/\1/p'

Früher habe ich sed, aber man kann genauso gut verwenden gawk / awk.

War nur ungern quantifiers gehen, bekommen nicht in der Lage, sondern läuft durch zwei reguläre Ausdrücke in Folge hat den Zweck erfüllt:

sed -E -e 's/^.{27}(.*).raw.gz$/\1/' << FOO | sed -E -e 's/-W[0-9.]+\+[0-9.]+$//'
20100613_M4_28007834.005_F_SOME-STRING.raw.gz
20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz
FOO
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top