Ich habe irgend wo ein bash Script,, welches ich mal vor Jahren selber geschrieben habe, welches meiner Erinnerung folgendes macht und Motivation ist mich bei Python um zu sehen um zu sehen ob ich das da auch hin bekomme.
Funktionsumfang:
* alle Zeilen einer Textdatei in ein Array laden
* alle Felder des Arrays die kein a2b7 enthalten aus dem Array entfernen
* fest stellen wie viel Felder das Array hat
* ein zufälliges Feld des Arrays aus wählen
* den gewählten Inhalt des Arrays an eine Variable übergeben
Das Würfeln einer Zeile aus einer bekannten Zeilenanzahl habe ich bereits unter py3 wie folgt hin bekommen:
from random import randint
# Arrayzelle würfeln
mindest_arrayzellen_zeilenanzahl = 0
gezäehlte_arrayzellen_zeilenanzahl = 6
gewürfelte_arrayzelle_zeile = randint(mindest_arrayzellen_zeilenanzahl, gezäehlte_arrayzellen_zeilenanzahl)
Wofür ich eine Idee benötige, ist wie man eine Textdatei in ein Array ein liest.
Unter bash hatte ich das mit folgendem gemacht:
Array_textdateizeilen=( `cat "textdatei.txt" `)
Wofür ich auch eine Idee benötige, ist wie man störende Zeichen entfernt. Unter bash hatte ich das wie folgt gemacht:
# Datei in Array kopieren, Leerzeilen und Zeilen, die mit "#" beginnen mit sed entfernen und mit tr die Zeilenumbrüche durch Leerzeilen ersetzen.
Array_textdateizeilen=($(sed -e '/^#.*/d' -e '/^$/d' textdatei.txt | tr '\n' ' '))
Wofür ich auch eine Idee benötige, ist wie man eine Textdatei in ein Array ein liest. Unter bash hatte ich das wie folgt gemacht:
# Feldanzahl des Arrays ermitteln
Array_Feldanzahl_ermittelt=${#Array_textdateizeilen[@]}
Vlt hat wer Ideen wie ich das in der mir bisher nicht bekannten Sprache Python 3 machen kann.
bestehendes bash script in Python übersetzen ? Übersetzer oder 1:1 Wörter buch ?
- __blackjack__
- User
- Beiträge: 14052
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Susann.M.23: Das was Du da Array nennst ist in Python eine Liste. Es gibt auch Arrays in Python, womit meistens Numpy-Arrays gemeint sind, und (viel) seltener der Datentyp, den das `array`-Modul aus der Standardbibliothek zur Verfügung stellt. Feld ist der deutsche Begriff für Array. Das ist auch in Bash verwirrend zu Fragen wieviele Felder ein Array hat. In Bash ist das sogar unmöglich weil es dort nur eindimensionale Arrays gibt.
Deine Variablennamen sind ziemlich heftig lang und man muss nicht jeden Wert an einen Namen binden.
Dieses array_zelle(n) ist in den Namen überflüssig/komisch/falsch, und das letzte Ergebnis ist keine gewürfelte Zeile, sondern der Index einer Zeile in der Liste mit den Zeilen. Die magische 6 steht so nicht im Code sondern wird aus der Liste mit den Zeilen ermittelt. Da bliebe dann das hier übrig wenn die Zeilen an den Namen `zeilen` gebunden sind:
Das ist aber falsch, weil das eine Zufallszahl von 0 bis einschliesslich ``len(zeilen)`` liefert, die Obergrenze davon aber kein gültiger Index mehr ist, da Indizes bei 0 beginnen. Da wäre die `random.randrange()`-Funktion passender. Allerdings gibt es mit `random.choice()` auch schon eine Funktion die genau das macht was Du willst: zufällig ein Element aus einer Sequenz auswählen:
Um die Zeilen einzulesen öffnet man die Datei mit `open()` zum Lesen. Bei Textdateien sollte man immer die Kodierung explizit angeben. Dateien sind iterierbar über ihre Zeilen, dass heisst man kann `list()` verwenden um die Zeilen alle in einer Liste zu sammeln. Da man Dateien wieder schliessen sollte, bietet sich die ``with``-Anweisung an um das sicherzustellen.
Wenn man mit den Zeilen beim Einlesen noch etwas machen will, beispielsweise nach Zeilen filtern die ein bestimmtes Kriterium erfüllen und/oder das Zeilenendezeichen entfernen, bietet sich eine „list comprehension“ an:
Python hat auch ein Modul für reguläre Ausdrücke in der Standardbibliothek (`re`), aber das was da mit ``sed`` mit Kommentarzeilen, Leerzeilen, und Zeilenenden gemacht wird, dafür sind reguläre Ausdrücke Kanonen auf Spatzen:
Wobei das im Endeffekt nicht dem Bash-Aufruf entspricht weil der ja an *allen* „whitespace“ trennt und nicht Zeilen in das Array einliest. Wobei dann auch der ``tr``-Teil unsinnig ist weil der nichts am Ergebnis ändert. Aber erst einmal das komplette Python-Programm bis hierher:
Zum Bash-Code:
Damit kann man zwar eine Datei einlesen, aber der Variablenname ist irreführend, denn das funktioniert so nur wenn in den Zeilen kein „whitespace“ vorkommt. Denn es wird nicht an Zeilenenden getrennt, sondern jegliches „whitespace“ wird normalisiert und dann wird daran getrennt. Zum einlesen von Zeilen hat die Bash ``readarray``:
Eine Möglichkeit das Python-Programm als Bash-Skript zu schreiben wäre das hier:
Wobei auch hier bei der Zuweisung an `zufaellige_zeile` wieder „whitespace“ normalisiert wird. Bash ist einfach nur
zum Programmieren.
Deine Variablennamen sind ziemlich heftig lang und man muss nicht jeden Wert an einen Namen binden.
Dieses array_zelle(n) ist in den Namen überflüssig/komisch/falsch, und das letzte Ergebnis ist keine gewürfelte Zeile, sondern der Index einer Zeile in der Liste mit den Zeilen. Die magische 6 steht so nicht im Code sondern wird aus der Liste mit den Zeilen ermittelt. Da bliebe dann das hier übrig wenn die Zeilen an den Namen `zeilen` gebunden sind:
Code: Alles auswählen
gewürfelter_zeilenindex = random.randint(0, len(zeilen))
Code: Alles auswählen
gewürfelte_zeile = random.choice(zeilen)
Code: Alles auswählen
with open("textdatei.txt", encoding="utf-8") as datei:
zeilen = list(datei)
Code: Alles auswählen
zeilen = [zeile.rstrip("\n") for zeile in datei if "a2b7" in zeile]
Code: Alles auswählen
zeilen = [
zeile.rstrip()
for zeile in datei
if zeile != "" and not zeile.startswith("#")
]
Code: Alles auswählen
#!/usr/bin/env python3
import random
def main():
with open("textdatei.txt", encoding="utf-8") as datei:
zeilen = [zeile.rstrip("\n") for zeile in datei if "a2b7" in zeile]
gewuerfelte_zeile = random.choice(zeilen)
print(gewuerfelte_zeile)
if __name__ == "__main__":
main()
Code: Alles auswählen
Array_textdateizeilen=(`cat "textdatei.txt"`)
Code: Alles auswählen
< 'test.txt' readarray Array_textdateizeilen
Code: Alles auswählen
#!/bin/bash
main() {
local -a zeilen
local zufaellige_zeile
< <(grep 'a2b7' 'test.txt') readarray zeilen
zufaellige_zeile=$(printf "%s" "${zeilen[@]}" | shuf -n 1)
echo "$zufaellige_zeile"
}
[[ "${BASH_SOURCE[0]}" == "$0" ]] && main
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 44
- Registriert: Montag 30. März 2020, 13:23
Erst einmal besten Dank für die umfassende Hilfe. Das muß ich erst einmal alles durch gehen, verarbeiten und versuchen zu verstehen.__blackjack__ hat geschrieben: Dienstag 31. März 2020, 01:34 @Susann.M.23: Das was Du da Array nennst ist in Python eine Liste.
...
...
...
Gruß
-
- User
- Beiträge: 44
- Registriert: Montag 30. März 2020, 13:23
Bedeutet das das man bestehende Bash Scripte irgend wie in Python ein binden kann ? Vlt. ein Stückchen bash in eine Python Datei ein binden oder ein in einer eigenen Datei steckendes .sh bash script von Python aus auf rufen kann ?__blackjack__ hat geschrieben: Dienstag 31. März 2020, 01:34
Eine Möglichkeit das Python-Programm als Bash-Skript zu schreiben wäre das hier:Wobei auch hier bei der Zuweisung an `zufaellige_zeile` wieder „whitespace“ normalisiert wird. Bash ist einfach nurCode: Alles auswählen
#!/bin/bash main() { local -a zeilen local zufaellige_zeile < <(grep 'a2b7' 'test.txt') readarray zeilen zufaellige_zeile=$(printf "%s" "${zeilen[@]}" | shuf -n 1) echo "$zufaellige_zeile" } [[ "${BASH_SOURCE[0]}" == "$0" ]] && main
zum Programmieren.
-
- User
- Beiträge: 44
- Registriert: Montag 30. März 2020, 13:23
Wenn das gehen sollte, bash Sequenzen in py3 Code ein fügen zu können oder seperate bash Dateien aus py3 auf zu rufen, wäre das durchaus spannend. Ich habe da noch eine Hand voll andere Sachen. Bei denen wäre es schon ganz witzig den Wuergaround mal aus zu probieren.__deets__ hat geschrieben: Dienstag 31. März 2020, 11:09 Das kann man, aber das ist ein ziemlich aetzender Wuergaround. Wuerde ich nicht empfehlen. Wie __blackjack__ ja schon schreibt, Bash und Listen/Arrays von Daten ist eher ein Albtraum.
Wenn man in Bash ein Array braucht (und das Feature gibt es ja auch noch nicht ewig), ist das, wie die anderen schon andeuteten, ein guter Hinweis dafür, dass man sich vielleicht nach einer anderen Sprache umsehen sollte. Das Eingangsproblem hätte man zum Beispiel (auch ohne Python und Bash-Arrays) "schon immer" in ein paar Zeilen mit awk relativ bequem lösen können.Susann.M.23 hat geschrieben: Dienstag 31. März 2020, 11:26 Wenn das gehen sollte, bash Sequenzen in py3 Code ein fügen zu können oder seperate bash Dateien aus py3 auf zu rufen, wäre das durchaus spannend. Ich habe da noch eine Hand voll andere Sachen. Bei denen wäre es schon ganz witzig den Wuergaround mal aus zu probieren.
Und wenn du eine Sprache haben möchtest, in die man leicht Shell-Scripting hineinmischen kann, wäre klassischerweise Perl im ersten Moment vielleicht die bessere Wahl; das ist die Sprache, die diese Nische früher besetut hat-- allerdings wird nach meiner Wahrnehmung heute häufig von Perl abgeraten und es wirkt etwas verschrieen. Aus meiner Sicht ist diese Vermischung jedenfalls eher schlechtes Design und ich würde das nicht empfehlen. In Python würde ich nur in Notfällen dazu übergehen, die Sprachen ohne Not zu mischen. Was man in Python sinnvoll lösen kann, sollte man in Python lösen -- und da Python eine recht gute Anbindung an Unix-Systeme hat, ist das sehr viel.
-
- User
- Beiträge: 44
- Registriert: Montag 30. März 2020, 13:23
Mal unabhängig davon das ich auch bash in der Vergangenheit hin und wieder angefasst habe und das auch nur mit mäßigem Erfolg, ist es so, das es für mich bei bash eigentlich nur einen Restvorteil gibt der mich bisher daran hindert ganz von bash zu lassen.nezzcarth hat geschrieben: Dienstag 31. März 2020, 11:35 In Python würde ich nur in Notfällen dazu übergehen, die Sprachen zu mischen. Was man in Python sinnvoll lösen kann, sollte man in Python lösen -- und da Python eine recht gute Anbindung an Unix-Systeme hat, ist das sehr viel.
Bei bash habe ich in der Vergangenheit nach langer Sucherei etwas gefunden gehabt, mit dem man ein gestartetes Programm, über den Programmnamen beenden kann. Bei py3 habe ich da bisher nichts in der Art gefunden.
Programm in bash starten:
muß ich heraus suchen
Programm in bash beenden, in etwa wie folgt:
pkill -9 -x klimaschranksteuerung
Wenn man so etwas auch mit py3 machen kann, dann kann ich meine vor Jahren geschriebenen kleinen bash Helferlein Stück um Stück durch py3 Helferlein ersetzen. (zu bestimmter uralter Software zur Steuerung vom Maschinen, von Firmen die es teilweise schon lange nicht mehr gibt) Dann habe ich auch gegenüber meinem Chef eine Begründung warum ich ein wenig nebenbei bei Python schmökere.
Wenn ich mich recht entsinne, hatten wir da allerdings zwei drei Instanzen der Klimaschranksteuerungssoftware gleichzeitig zu laufen, die jeweils per bash nicht nur gestartet, sondern eben auch die jeweils gewünschte Instanz des Klimaschrankprogrammes beendet werden konnte.
Zuletzt geändert von Susann.M.23 am Dienstag 31. März 2020, 12:07, insgesamt 2-mal geändert.
Du meinst pgrep oder sowas? Man kann in Python zB das psutil-Modul benutzen, muss aber extra installiert werden. Alternativ ist es ja auch ok, *einzelne* Dinge mit Unterprozessen zu loesen. Also zb sowas in der Art, ungetestet:
Code: Alles auswählen
import os
import signal
import subprocess
def kill_process_with_name(name):
p = supbrocess.run(["ps", "aux"], capture_output=True, check=True)
for line in p.stdout.split("\n"):
if name in line:
pid = line.strip().split()[0]
os.kill(int(pid), signal.SIGINT) # oder was auch immer
-
- User
- Beiträge: 44
- Registriert: Montag 30. März 2020, 13:23
Unter Linux da bei uns noch etwas zu installieren wäre kein Problem. Da habe ich wohl die Rechte.__deets__ hat geschrieben: Dienstag 31. März 2020, 11:59 Du meinst pgrep oder sowas? Man kann in Python zB das psutil-Modul benutzen, muss aber extra installiert werden. Alternativ ist es ja auch ok, *einzelne* Dinge mit Unterprozessen zu loesen. Also zb sowas in der Art, ungetestet:
Code: Alles auswählen
import os import signal import subprocess def kill_process_with_name(name): p = supbrocess.run(["ps", "aux"], capture_output=True, check=True) for line in p.stdout.split("\n"): if name in line: pid = line.strip().split()[0] os.kill(int(pid), signal.SIGINT) # oder was auch immer
Das waere dann hier: https://psutil.readthedocs.io/en/latest/
Ggf. ist das auch schon Teil des Paketmanagements deines Systems.
Ggf. ist das auch schon Teil des Paketmanagements deines Systems.
-
- User
- Beiträge: 44
- Registriert: Montag 30. März 2020, 13:23
Das Installieren ist kein Problem, es ist eher die Frage wie man die Möglichkeiten benutzt. Ich bin halt kein Programmierer.__deets__ hat geschrieben: Dienstag 31. März 2020, 12:11 Das waere dann hier: https://psutil.readthedocs.io/en/latest/
Ggf. ist das auch schon Teil des Paketmanagements deines Systems.
Also so etwas wie:
Programm drei gleiche Programme öffnen und einzelne der geöffneten Programme gezielt wieder schließen schließen unter py3
Da muß ich mal suchen. Mal sehen ob ich da ein Beispeil finde.
- __blackjack__
- User
- Beiträge: 14052
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Klimaschranksteuerung unter Linux starten und stoppen hört sich für mich nach gar keiner Programmierssprache an, sondern nach einem Fall für systemd-Units.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari