staging.inyokaproject.org

Mit grep nach Zahl grösser als suchen

Status: Gelöst | Ubuntu-Version: Ubuntu 14.04 (Trusty Tahr)
Antworten |

ka111

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Wie kann ich mit grep nach einer Zahl suchen die grösser als zB. 5 ist?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

Nur sehr umständlich... grep -E '([6789]|[1-9][0-9]+)'

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Ah ok. Danke

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Ich hätte noch eine erweiterte Frage dazu: Wie kann ich diese Zeile:

897,466: (25700,22873,21588) #645954 srgb(100,89,84)

in einem grep Befehl nach den rgb Werten von 0-255 rechts in den Klammern durchsuchen, so das ich zB. nur Zeilen finde die Rot kleiner als 80 haben, Grün grösser als 50, und Blau grösser als 0 haben? Und könnte man dazu auch im gleichen grep Befehl noch wenn so eine Zeile kommt:

910,466: (48573,48573,48573) #BDBDBD grey74

diese zB. auch ausgeben weil dieses Grau in den Suchkriterien von Rot<80, Grün>50, Blau>0 auch enthalten ist?

Zu beachten ist auch das nicht immer 3 Zahlen stehen wenn die Zahl nicht grösser als 99 ist, und das es nur bis 255 gehen darf weil es sonnst vielleicht wieder die Zahlen im linken Klammern Feld findet.

Das wäre super wenn man das alles in einem grep Befehl machen könnte, sonnst alternativ mit einem einzigen anderen Befehl wie awk oder sed der ein Bild das mit imagemagick zu .txt convertiert wurde (und für jeden Pixel eine Zeile steht) einigermassen schnell durchsuchen kann. Also eine while Schleife mit 1. Zeile durchsuchen, 2. Zeile durchsuchen ... wird glaube ich extrem langsam.

Oder gibt es einen (einfachen) besseren Weg um in einem Bild jeden Pixel nach rgb Werten zu durchsuchen mit bash?

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Ich habe es herausgefunden, mit:

grep -e{0..255},{0..255}, /pfad/zum/bild.txt

sucht es die ersten beiden Farben heraus, und wenn ich das in einer anderen Datei speichere kann ich ein 2. Mal nach ",{0..255},{0..255}" suchen. Leider kommt mit "{0..255},{0..255},{0..255}" immer "bash: /bin/grep: Die Argumentliste ist zu lang". Und in einer Variable kann ich es irgendwie auch nicht zwischenspeichern, weil es danach nicht mehr mehrere Zeilen hat sondern nur noch eine mit allen Zeilen durch ein Leerzeichen getrennt, und dann funktioniert es irgendwie nicht mehr. Und es funktioniert auch nur genug schnell (in ein paar Sekunden) auf meinem mehr oder weniger neuen Pc, auf einem alten 32bit Laptop funktioniert es unproportional langsam, so ca 1s pro 10 Pixel.

Wenn jemand noch eine Lösung weis wegen der zu langen Argumentliste, der Variable mit nur einer Zeile und der Zeile mit grey74 wäre es natürlich super, aber sonnst funktioniert es auch so für mich im Moment.

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

grep ist grauenhaft für die Problemstellung, aber wenns unbedingt sein muss, ist es wohl am besten, hier nach den auch angezeigten Hexadezimalwerten zu gehen. Insb. wenn das letzte r,g,b auch durch irgendwelche Farbnamen (grey74) ersetzt wird, damit kann man ja nicht arbeiten.

Also, du suchst #645954 bzw. #BDBDBD

Da musst du dich eben mit Hexadezimalwerten beschäftigen:

$ echo $((0x64))
100
$ printf "%x\n" 100
64
$ echo $((0xBD))
189
$ printf "%x\n" 189
bd

So kannst du die Dinger umwandeln. 00 ist 0, FF ist 255...

Eine Regexp für 0-255 dementsprechend [0-9A-F][0-9A-F]

zB. nur Zeilen finde die Rot kleiner als 80 haben, Grün grösser als 50, und Blau grösser als 0 haben?

Größer als 0 ist alles außer 00, also 0[1-9A-F]|[1-9A-F][0-9A-F]

Größer als 50? Was ist 50 in Hex, printf %x → 0x32. Also 3[3-9A-F]|[4-9A-F][0-9A-F]

Kleiner als 80? 80 ist 0x50 in Hex, also [0-4][0-9A-F]

Alles zusammen suchst du nach #([0-4][0-9A-F])(3[3-9A-F]|[4-9A-F][0-9A-F])(0[1-9A-F]|[1-9A-F][0-9A-F])

So ungefähr, habs jetzt nicht ausprobiert, Fehler darfst du behalten, etc.

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Das ist eine gute Idee mit den Hexadezimal Zahlen, so kann ich auch nach allen 3 Farben in einem Befehl suchen. Ich verstehe nur nicht ganz wieso man das so schreiben muss wie du es schreibst mit [0-9A-F], wieso immer 9A zwischen dem Zahlenbereich? Und um grösser als 5 zu suchen muss ich immer "0[5-F]|[1-F][0-F]"? Das ist irgendwie sehr mühsam um sich das für 3 zweistellige Hexadezimal Zahlen vorzustellen, geht das nicht auch irgendwie mit {0..FF}? Oder sonst irgendwie mit mehr als 0 - F?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

Du kannst auch 0-F schreiben aber dann würde es auch :⇐>?@ matchen (siehe ASCII-Tabelle) statt nur 0 bis 9 und A bis F.

geht das nicht auch irgendwie mit {0..FF}?

Nein, grep ( Regexp ) ist einfach nicht für Zahlenbereiche gemacht.

In einem richtigen Programm könntest du die Bilddatei selbst einlesen und Zahlenwerte direkt vergleichen. Sehr ungeschickt das erst in Text zu verwandeln und dann wieder den Text zu parsen für.

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Achso, das bedeutet 0 bis 9 und A bis F, ich hatte das so interpretiert das es 0 bis 9A bis F heisst...

Aber wenn man auch mit Buchstaben zählen kann, wieso kann ich das nicht auch an Zahlen gekoppelt mit { } machen? Es funktioniert sogar nur nach einem Zahlen- oder Buchstabenbereich zu suchen mit "-e{A..F}", aber wie kann ich da noch "oder 0-9" hinzufügen? Das kriege ich nicht hin, mit "-e{0..9A..F}" nicht und auch nicht mit | und [ ]. Gibt es keine Möglichkeit bei -e{ } noch ein oder hinzuzufügen? Wieso muss dieses e eigentlich ohne Abstand an der Klammer stehen?

Was meinst du mit richtigen Programm, ein grafisches Programm? Oder einfach ein anderer Befehl? Ich brauche die Werte von den gesuchten Pixeln nachher in einem bash Script...

Edit: Ah nein, das ist glaube ich ein Denkfehler mit {1..9}|{A..F} und kommt wieder auf genau das gleiche heraus wie mit [0-9A-F]... Ich müsste richtig in Hexadezimal zählen können. Gibt es den einen anderen einfacheren Befehl der mir die rgb Werte in einem bash Script etwa mindestens so schnell wie mit grep heraus sucht?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

Wieso muss dieses e eigentlich ohne Abstand an der Klammer stehen?

Die -e{} Syntax gibt es gar nicht, tatsächlich machst du hier Bash Expansion

also grep -e{0..9} ist wirklich grep -e0 -e1 -e2 -e3 -e4 -e5 -e6 -e7 -e8 -e9 (bis irgendwann Argument list too long...)

Was meinst du mit richtigen Programm, ein grafisches Programm? Oder einfach ein anderer Befehl?

Bilddateien sind nun mal keine Textdateien... grep ist da einfach der falsche Ansatz

Mit Python oder jeder anderen Programmiersprache die dein Bildformat unterstützt, kannst du dann direkt mit den Farbwerten in Pixeln arbeiten ohne den Text-Zwischenschritt.

https://en.wikibooks.org/wiki/Python_Imaging_Library/Editing_Pixels (in dem Beispiel werden Pixel gesetzt, aber du könntest sie genausogut auch abfragen)

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Achso, ok... Bei Phyton müsste ich alles zuerst nochmals neu anschauen wie man alles macht was ich mit bash kann, und ich habe keine Übung darin, so das alles viel länger geht als wenn ich es mit bash mache. Ich glaube ich verwende einfach grep mit [ ], es kommt dieses mal auch nicht darauf an ob es 5s oder 20s dauert. Und sonnst kann ich es ja später nochmals anschauen.

Danke für die Hilfe

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

In Ruby ist das auch recht einfach.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/ruby

ARGF.each_line do |line|
  rgb = line[/(?<=#)\h{6}/]

  if rgb
    r, g, b = rgb.scan(/\h{2}/).map {|s| Integer(s, 16)}
    puts line if r < 80 && g > 50 && b > 0
  end
end

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Danke für den Tipp, aber eine andere Sprache als shell/bash und ein bisschen Phyton kann ich nicht, und für mich sieht das nicht grad einfach aus mit allen Sonderzeichen (:

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

ka111 schrieb:

Danke für den Tipp, aber eine andere Sprache als shell/bash und ein bisschen Phyton kann ich nicht, und für mich sieht das nicht grad einfach aus mit allen Sonderzeichen (:

Ich bin natürlich im Vorteil, aber generell finde ich Ruby-Code immer sehr lesbar (verglichen mit C++ z.B.).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Shebang

Für jede Zeile aus Stdin oder den Dateien, die auf der Kommandozeile angegeben sind
  extrahiere Sequenz aus 6 Hex-Zeichen, vor denen ein "#" steht in die Variable "rgb"

  Falls gefunden
    Scanne Sequenzen von 2 Hex-Zeichen und konvertiere jedes Ergebnis in einen Int. Speichere in den Variablen "r, g, b".
    Gib die Zeile aus, sofern r, g und b den angegebenen Kriterien entsprechen
  ende Falls
ende Für jede

ka111

(Themenstarter)

Anmeldungsdatum:
22. Juni 2014

Beiträge: 141

Leider kann ich gar keine andere Sprache, die Darstellung und alle Sonderzeichen müsste ich zuerst neu auswendig lernen...

Antworten |