2010-06-18 17 views
11

Bien, entonces estoy usando Perl para leer en un archivo que contiene algunos datos de configuración general. Esta información está organizada en encabezados según lo que significan. Un ejemplo es el siguiente:Usar perl para dividir una línea que puede contener espacios en blanco

[vars] 

# This is how we define a variable! 
$var = 10; 
$str = "Hello thar!"; 


# This section contains flags which can be used to modify module behavior 
# All modules read this file and if they understand any of the flags, use them 
[flags] 
    Verbose =  true; # Notice the errant whitespace! 

[path] 
WinPath = default; # Keyword which loads the standard PATH as defined by the operating system. Append with additonal values. 
LinuxPath = default; 

Objetivo: El uso de la primera línea como un ejemplo "$ var = 10;", me gustaría utilizar la función de división en Perl para crear una matriz que contiene los caracteres "$ var "y" 10 "como elementos. El uso de otra línea como un ejemplo:

Verbose =   true; 
    # Should become [Verbose, true] aka no whitespace is present 

Esto es necesario porque voy a dar salida a estos valores en un nuevo archivo (que leerá una pieza diferente de código C++) para crear instancias de objetos de diccionario. Sólo para dar una pequeña muestra de lo que podría ser similar (inventando sobre la marcha):

define new dictionary 
name: [flags] 
# Start defining keys => values 
new key name: Verbose 
new value val: 10 
# End dictionary

Ah, y aquí está el código que tengo actualmente, junto con lo que está haciendo (incorrectamente) :

sub makeref($) 
{ 
    my @line = (split (/=/)); # Produces ["Verbose", " true"]; 
} 

para responder a una pregunta, ¿por qué no estoy utilizando Config :: simple, es que inicialmente no sabía lo que mi archivo de configuración se vería así, sólo lo que quería que hiciera. Lo inventé a medida que avanzaba, al menos lo que me pareció sensato, y usé Perl para analizar el archivo.

El problema es que tengo un código C++ que cargará la información en el archivo de configuración, pero como el análisis en C o C++ es :(Decidí usar Perl. También es un buen ejercicio de aprendizaje para mí ya que soy nuevo al lenguaje. Así que ese es el problema, este código perl no es realmente parte de mi aplicación, simplemente hace que sea más fácil para el código C++ leer la información. Y es más legible (tanto el archivo de configuración como el archivo generado).). Gracias por los comentarios, lo que realmente ayudó.

+1

No utilice prototipos a menos que sean necesarios. Incluso entonces, piensa tres veces. http://perldoc.perl.org/perlsub.html#Prototypes * Todo esto es muy poderoso, por supuesto, y debe usarse solo con moderación para hacer del mundo un lugar mejor. * –

+0

Consulte la respuesta de FM. Realmente no debería estar escribiendo su propio analizador de archivos para realizar un trabajo tan común y estándar: use CPAN y concéntrese en la lógica de su aplicación. – Ether

Respuesta

6

Si usted está haciendo esto sea interpretado como un ejercicio de aprendizaje, eso está bien. Sin embargo, CPAN tiene varios módulos que harán mucho del trabajo por usted.

use Config::Simple; 
Config::Simple->import_from('some_config_file.txt', \my %conf); 
+0

Sí, realmente tengo que preguntar por qué el OP está usando lo que es muy similar a un formato de archivo de configuración estándar, pero no utiliza los módulos de lectura de archivos de configuración estándar que están disponibles y muy bien probados. (YAML es otra buena opción si Config :: Simple no coincide exactamente con el formato deseado). – Ether

+0

95% time Esto es lo que se querría. Tengo algunas razones (aprender, no todo mi código está en Perl) que hacen que sea más fácil hacerlo de otra manera. –

2

parece que lo tienes. despojar a los espacios en blanco antes de separarse.

sub makeref($) 
{ 
    s/\s+//g; 
    my @line = (split(/=/)); # gets ["verbose", "true"] 
} 
+0

Ahh es tan obvio ahora. Gracias, soy nuevo en Perl y es un lenguaje genial. –

+0

De nada. Espero eso ayude. –

+0

¡Curiosamente, chomp no mastica espacios en blanco! –

1

Este código hace el truco (y es más eficiente sin invertir).

for (@line) { 
    s/^\s+//; 
    s/\s+$//; 
} 
+0

puede agregar una 'g' al final de la expresión regular para que reemplace más de una apariencia extra de espacio en blanco. es decir 's/^ \ s + // g;' –

+0

Tenga en cuenta el resaltado de sintaxis desordenado. – Svante

+0

Hay muchos módulos que manejan secciones de configuración, líneas de continuación, variables con valores múltiples, etc. en CPAN. Use uno de ellos una vez que haya terminado de aprender. Me gusta 'Config :: Std'. @FM señaló 'Config :: Simple'. –

3

split fracturas en una expresión regular, por lo que simplemente puede poner el espacio en blanco alrededor de la señal de = en su expresión regular:

split (/\s*=\s*/, $line); 

Obviamente no desea eliminar todo espacios en blanco, o tales se produciría una línea (falta el espacio en blanco en la cadena):

$str="Hellothere!"; 

Supongo que en Ly eliminar los espacios en blanco del principio y final de la línea es suficiente:

$line =~ s/^\s*(.*?)\s*$/$1/; 

Una alternativa más simple con dos declaraciones:

$line =~ s/^\s+//; 
$line =~ s/\s+$//; 
+0

Tenga en cuenta el resaltado de sintaxis desordenado. – Svante

+0

Es por eso que tiendo a usar 's {...} {...}' al publicar en SO. –

+1

's/^ \ s + //' es un poco más eficiente. –

0

Probablemente lo tengas todo resuelto, pero pensé que agregaría un poco. Si

sub makeref($) 
{ 
    my @line = (split(/=/)); 
    foreach (@line) 
    { 
     s/^\s+//g; 
     s/\s+$//g; 
    } 
} 

entonces usted va a eliminar el espacio en blanco antes y después de que tanto el lado izquierdo y derecho. De esa manera algo como:

this is a parameter   =  all sorts of stuff here 

no tendrá espacios locos.

!! Advertencia: ¡probablemente no sé de lo que estoy hablando!

Cuestiones relacionadas