peddy
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Hallo, ich habe eine Datei die nach folgendem Schema aufgebaut ist:
Username Permission 2100
anton view-space T
anton remove-own F
anton page-add T
anton page-remove F
anton attachment-add F
anton attachment-remove F
petra view-space F
petra remove-own F
petra page-add F
petra page-remove F
petra attachment-add F
petra attachment-remove F
...
Nun würde ich gerne User komplett aus der Datei entfernen, wenn bei ihnen in der dritten Spalte immer ein F steht. In diesem Fall wäre das nur petra. Geht so was?
|
misterunknown
Ehemalige
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
sed -ri "/^petra.*F$/d" file Edit: Das kannst du aber auch gleich mit in das AWK einbauen, wenn du damit sowieso an die Datei rangehst. Edit 2: So könnte das dann aussehen:
awk '!/^petra.*F$/ { if ($8 == "P") $8="Partial"; else if ($8 == "T") $8="True"; else if ($8 == "F") $8="False"; print $1,$2,$3,$8 }' file
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4577
Wohnort: Berlin
|
@misterunknown: Ich glaube Du hast die Frage falsch verstanden: Es soll nicht petra entfernt werden sondern die Benutzer bei denen nur Fs stehen. Das ist in dem Beispiel zufällig petra, aber eben nicht immer/nur. ☺
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
misterunknown schrieb: sed -ri "/^petra.*F$/d" file Edit: Das kannst du aber auch gleich mit in das AWK einbauen, wenn du damit sowieso an die Datei rangehst. Edit 2: So könnte das dann aussehen:
awk '!/^petra.*F$/ { if ($8 == "P") $8="Partial"; else if ($8 == "T") $8="True"; else if ($8 == "F") $8="False"; print $1,$2,$3,$8 }' file
Bei beiden Ansätzen fehlt aber noch die Ermittlung, welche Nutzer denn gelöscht werden sollen! Man kann das recht elegant mit zwei Durchgängen machen: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | $ cat x
Username Permission 2100
anton view-space T
anton remove-own F
anton page-add T
anton page-remove F
anton attachment-add F
anton attachment-remove F
petra view-space F
petra remove-own F
petra page-add F
petra page-remove F
petra attachment-add F
petra attachment-remove F
$ awk 'NR==FNR && $3=="T" {show[$1]=1} NR!=FNR && show[$1]' x x
anton view-space T
anton remove-own F
anton page-add T
anton page-remove F
anton attachment-add F
anton attachment-remove F
|
Oder, mit Header: | $ awk 'NR==FNR && $3!="F" {show[$1]=1} NR!=FNR && show[$1]' x x
Username Permission 2100
anton view-space T
anton remove-own F
anton page-add T
anton page-remove F
anton attachment-add F
anton attachment-remove F
|
|
peddy
(Themenstarter)
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Marc_BlackJack_Rintsch schrieb: @misterunknown: Ich glaube Du hast die Frage falsch verstanden: Es soll nicht petra entfernt werden sondern die Benutzer bei denen nur Fs stehen. Das ist in dem Beispiel zufällig petra, aber eben nicht immer/nur. ☺
So wie du es sagst habe ich es gemeint.
|
peddy
(Themenstarter)
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Wie man oben in dem Beispiel von mir sieht, hat jeder User 6 zeilen, in denen die Berechtigungen angezeigt werden. Kann man mit awk immer 6 Zeilen gleichzeitig einlesen und diese auswerten? Sollte in Spalte 3 immer ein F gefunden werden soll der User komplett entfernt werden.
|
misterunknown
Ehemalige
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
Ah ok, wer lesen kann ist klar im Vorteil 😉
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4577
Wohnort: Berlin
|
@peddy: Das kann man machen, denn man kann innerhalb einer Aktion auf ein Muster auch explizit weitere Zeilen lesen. Allerdings benutzt man in dem Fall bei diesem Problem die typische AWK-Struktur, die Muster auf Aktionen abbildet nicht mehr. Da würde ich sagen ist AWK dann das falsche Werkzeug und man würde eher eine allgemeinere Programmiersprache verwenden. Funktioniert die Lösung vom rklm denn nicht? Oder hast Du tatsächlich so viele Datensätze, das zwei Durchgänge zu langsam sind? Wobei der zweite Durchgang ziemlich wahrscheinlich deutlich schneller ist, wenn die Daten aus dem Cache und nicht mehr vom Hintergrundspeicher kommen.
Edit: Eine Lösung in Python die mit einem Lesedurchlauf auskommt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 | import csv
from itertools import groupby
import logging
from operator import itemgetter
logging.basicConfig()
DELIMITER = '\t'
ROWS_PER_USER_NAME = 6
def main():
with open('test2.csv') as in_file:
reader = csv.reader(in_file, delimiter=DELIMITER)
with open('test3.csv', 'w') as out_file:
writer = csv.writer(out_file, delimiter=DELIMITER)
writer.writerow(next(reader)) # Copy header.
for user_name, group in groupby(reader, itemgetter(0)):
group = list(group)
if len(group) != ROWS_PER_USER_NAME:
logging.warning(
'User name "%s" has %d rows instead of %d!',
user_name,
len(group),
ROWS_PER_USER_NAME,
)
if not all(row[2].strip() == 'F' for row in group):
writer.writerows(group)
if __name__ == '__main__':
main()
|
|
peddy
(Themenstarter)
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Den Beitrag von rklm hatte ich erst falsch interpretiert. Habe mir die Zeile | awk 'NR==FNR && $3!="F" {show[$1]=1} NR!=FNR && show[$1]' x x
|
noch mal angesehen und getestet. Ich verstehe zwar nicht wie die Funktionsweise ist aber es geht.
|
peddy
(Themenstarter)
Anmeldungsdatum: 31. Oktober 2006
Beiträge: 162
Wohnort: Mainz
|
Marc_BlackJack_Rintsch schrieb: @peddy: Das kann man machen, denn man kann innerhalb einer Aktion auf ein Muster auch explizit weitere Zeilen lesen. Allerdings benutzt man in dem Fall bei diesem Problem die typische AWK-Struktur, die Muster auf Aktionen abbildet nicht mehr. Da würde ich sagen ist AWK dann das falsche Werkzeug und man würde eher eine allgemeinere Programmiersprache verwenden. Funktioniert die Lösung vom rklm denn nicht? Oder hast Du tatsächlich so viele Datensätze, das zwei Durchgänge zu langsam sind? Wobei der zweite Durchgang ziemlich wahrscheinlich deutlich schneller ist, wenn die Daten aus dem Cache und nicht mehr vom Hintergrundspeicher kommen.
Edit: Eine Lösung in Python die mit einem Lesedurchlauf auskommt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 | import csv
from itertools import groupby
import logging
from operator import itemgetter
logging.basicConfig()
DELIMITER = '\t'
ROWS_PER_USER_NAME = 6
def main():
with open('test2.csv') as in_file:
reader = csv.reader(in_file, delimiter=DELIMITER)
with open('test3.csv', 'w') as out_file:
writer = csv.writer(out_file, delimiter=DELIMITER)
writer.writerow(next(reader)) # Copy header.
for user_name, group in groupby(reader, itemgetter(0)):
group = list(group)
if len(group) != ROWS_PER_USER_NAME:
logging.warning(
'User name "%s" has %d rows instead of %d!',
user_name,
len(group),
ROWS_PER_USER_NAME,
)
if not all(row[2].strip() == 'F' for row in group):
writer.writerows(group)
if __name__ == '__main__':
main()
|
Vielen Dank für deine Unterstützung.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
peddy schrieb:
Ich verstehe zwar nicht wie die Funktionsweise ist aber es geht.
Fragen ist auch immer eine Option. ☺
|