2015-02-17 17 views
6

Ho un grande file di dati in formato testo e voglio convertirlo in csv specificando ogni lunghezza di colonna.convertire un file a larghezza fissa dal testo in csv

numero di colonne = 5

lunghezza colonna

[4 2 5 1 1] 

campione osservazioni:

aasdfh9013512 
ajshdj 2445df 

output previsto

aasd,fh,90135,1,2 
ajsh,dj, 2445,d,f 

risposta

19

GNU awk (gawk) supporta questo direttamente con FIELDWIDTHS, ad esempio:

gawk '$1=$1' FIELDWIDTHS='4 2 5 1 1' OFS=, infile 

uscita:

aasd,fh,90135,1,2 
ajsh,dj, 2445,d,f 
+3

Bello! Non ero a conoscenza di questa funzionalità. grande +1! Collegamento: [Lettura dati a larghezza fissa] (http://web.mit.edu/gnu/doc/html/gawk_5.html#SEC27) – fedorqui

+0

L'argomento "FIELDWIDTHS" funziona solo per me se installo e utilizzo 'gawk '; su Ubuntu 14.04.3. – Arthur

+0

@Arthur: in base alla [cronologia delle caratteristiche di GNU awk] (https://www.gnu.org/software/gawk/manual/html_node/Feature-History.html), FIELDWIDTHS è disponibile da gawk 2.13, ovvero a luglio 2010. – Thor

2

userei sed un ND catturare i gruppi con la lunghezza data:

$ sed -r 's/^(.{4})(.{2})(.{5})(.{1})(.{1})$/\1,\2,\3,\4,\5/' file 
aasd,fh,90135,1,2 
ajsh,dj, 2445,d,f 
+0

Prima di tutto, grazie per rispondere a questa. Ma nel file effettivo devo romperlo su 80 colonne e il comando sed funziona solo su 9 colonne. Per favore aiuto. – Ashish

+0

@AshishKumar quindi probabilmente devi usare la risposta di Thor con 'awk'. – fedorqui

0

Se qualcuno è ancora cercando una soluzione, ho sviluppato un piccolo script in python. la sua facile da usare a patto di avere python 3,5

https://github.com/just10minutes/FixedWidthToDelimited/blob/master/FixedWidthToDelimiter.py

""" 
This script will convert Fixed width File into Delimiter File, tried on Python 3.5 only 
Sample run: (Order of argument doesnt matter) 
python ConvertFixedToDelimiter.py -i SrcFile.txt -o TrgFile.txt -c Config.txt -d "|" 
Inputs are as follows 
1. Input FIle - Mandatory(Argument -i) - File which has fixed Width data in it 
2. Config File - Optional (Argument -c, if not provided will look for Config.txt file on same path, if not present script will not run) 
    Should have format as 
    FieldName,fieldLength 
    eg: 
    FirstName,10 
    SecondName,8 
    Address,30 
    etc: 
3. Output File - Optional (Argument -o, if not provided will be used as InputFIleName plus Delimited.txt) 
4. Delimiter - Optional (Argument -d, if not provided default value is "|" (pipe)) 
""" 
from collections import OrderedDict 
import argparse 
from argparse import ArgumentParser 
import os.path 
import sys 


def slices(s, args): 
    position = 0 
    for length in args: 
     length = int(length) 
     yield s[position:position + length] 
     position += length 

def extant_file(x): 
    """ 
    'Type' for argparse - checks that file exists but does not open. 
    """ 
    if not os.path.exists(x): 
     # Argparse uses the ArgumentTypeError to give a rejection message like: 
     # error: argument input: x does not exist 
     raise argparse.ArgumentTypeError("{0} does not exist".format(x)) 
    return x 





parser = ArgumentParser(description="Please provide your Inputs as -i InputFile -o OutPutFile -c ConfigFile") 
parser.add_argument("-i", dest="InputFile", required=True, help="Provide your Input file name here, if file is on different path than where this script resides then provide full path of the file", metavar="FILE", type=extant_file) 
parser.add_argument("-o", dest="OutputFile", required=False, help="Provide your Output file name here, if file is on different path than where this script resides then provide full path of the file", metavar="FILE") 
parser.add_argument("-c", dest="ConfigFile", required=False, help="Provide your Config file name here,File should have value as fieldName,fieldLength. if file is on different path than where this script resides then provide full path of the file", metavar="FILE",type=extant_file) 
parser.add_argument("-d", dest="Delimiter", required=False, help="Provide the delimiter string you want",metavar="STRING", default="|") 

args = parser.parse_args() 

#Input file madatory 
InputFile = args.InputFile 
#Delimiter by default "|" 
DELIMITER = args.Delimiter 

#Output file checks 
if args.OutputFile is None: 
    OutputFile = str(InputFile) + "Delimited.txt" 
    print ("Setting Ouput file as "+ OutputFile) 
else: 
    OutputFile = args.OutputFile 

#Config file check 
if args.ConfigFile is None: 
    if not os.path.exists("Config.txt"): 
     print ("There is no Config File provided exiting the script") 
     sys.exit() 
    else: 
     ConfigFile = "Config.txt" 
     print ("Taking Config.txt file on this path as Default Config File") 
else: 
    ConfigFile = args.ConfigFile 

fieldNames = [] 
fieldLength = [] 
myvars = OrderedDict() 


with open(ConfigFile) as myfile: 
    for line in myfile: 
     name, var = line.partition(",")[::2] 
     myvars[name.strip()] = int(var) 
for key,value in myvars.items(): 
    fieldNames.append(key) 
    fieldLength.append(value) 

with open(OutputFile, 'w') as f1: 
    fieldNames = DELIMITER.join(map(str, fieldNames)) 
    f1.write(fieldNames + "\n") 
    with open(InputFile, 'r') as f: 
     for line in f: 
      rec = (list(slices(line, fieldLength))) 
      myLine = DELIMITER.join(map(str, rec)) 
      f1.write(myLine + "\n") 
0

Ecco una soluzione che funziona con la normale awk (non richiede gawk).

awk -v OFS=',' '{print substr($0,1,4), substr($0,5,2), substr($0,7,5), substr($0,12,1), substr($0,13,1)}' 

Si utilizza la funzione di awk substr per definire la posizione di inizio di ciascun campo e durata. OFS definisce il separatore del campo di output (in questo caso una virgola).

(Nota a margine:.. Questo funziona solo se i dati di origine non ha virgole se i dati sono le virgole, allora dovete sfuggire loro di essere corretta CSV, che è oltre la portata di questa domanda)

Demo:

echo 'aasdfh9013512 
ajshdj 2445df' | 
awk -v OFS=',' '{print substr($0,1,4), substr($0,5,2), substr($0,7,5), substr($0,12,1), substr($0,13,1)}' 

uscita:

aasd,fh,90135,1,2 
ajsh,dj, 2445,d,f 
Problemi correlati