Sortera textfil på fält som kan vara i olika kolumner
Postat: 29 oktober 2022, 14:07:26
Jag har en återkommande uppgift som jag inte lyckats lösa med "de vanliga" unix-komandona (grep, sort, elementär awk och sed...).
Problemet: sortera en stor textfil på talet som står efter 'id: '. Detta kan komma i olika kolumner. Filen kan vara mycker stor.
Följande lösning fungerar men den tar för lång tid (grep:a ut alla id-nummer, loopa över dessa och grep:a ut de tillhörande raderna):
Denna lösning funkar bra för obegräsat stora filer men ger inte en sorterad fil utan en ny fil per id. Skulle iofs gå att cat:a ihop dessa till en ny stor. Och så använder den scriptspråk:
En lösning till som också använder scriptspråk delvis (plockar ut id-numret och lägger till det i en ny första kolumn, sorterar på första kolumnen, tar bort första kolumnen):
Och en lösning till som avänder scriptspråk rakt av. (läser in alla rader i en array, sorterar arrayen) Tar en massa minne (krasch!) och är slött. unix-sort känns stabilare:
Jag har alltså lösningar på det men jag undrar om man måste ta till scriptspråk?
Någon som har en idé?
Problemet: sortera en stor textfil på talet som står efter 'id: '. Detta kan komma i olika kolumner. Filen kan vara mycker stor.
$ cat fil af asf id: 2 af af asdf id: 4 asdf af id: 3 asdf af asfd asf asdf id: 2 as
Följande lösning fungerar men den tar för lång tid (grep:a ut alla id-nummer, loopa över dessa och grep:a ut de tillhörande raderna):
for i in `cat fil | grep -oP 'id: \d+' | grep -oP '\d+' | sort -g | uniq`;do cat fil | grep "id: $i";done
Denna lösning funkar bra för obegräsat stora filer men ger inte en sorterad fil utan en ny fil per id. Skulle iofs gå att cat:a ihop dessa till en ny stor. Och så använder den scriptspråk:
cat fil | ruby -ne 'BEGIN{f={}};i=$_[/id: (\d+)/,1];g=f;if not g then f=File.open(i, "w") end;f.puts($_)'
En lösning till som också använder scriptspråk delvis (plockar ut id-numret och lägger till det i en ny första kolumn, sorterar på första kolumnen, tar bort första kolumnen):
cat fil | ruby -ne 'print $_[/id: (\d+)/,1];print " "; puts $_' | sort -g -k 1,1 | sed 's/^[0-9]* //g'
Och en lösning till som avänder scriptspråk rakt av. (läser in alla rader i en array, sorterar arrayen) Tar en massa minne (krasch!) och är slött. unix-sort känns stabilare:
cat fil | ruby -e 'r=ARGF.readlines; r.sort!{|a,b| x=a[/id: (\d+)/, 1].to_i;y=b[/id: (\d+)/,1].to_i;x<=>y};puts r'
Jag har alltså lösningar på det men jag undrar om man måste ta till scriptspråk?
Någon som har en idé?