2009-08-10 11 views
1

J'essaie de convertir un grand nombre de fichiers d'une mise en page en texte brut au format CSV. Les premières lignes de l'un des fichiers ressemble à ceci:sed: Ajouter une ligne à chaque ligne avec l'espace de stockage

SLICE AT X= -0.25 
    ELEM NO   XI-COORD    INWARD-NORMAL 
1  0  0.000 0.000 0.000  0.000 0.000 0.000 
2  0  0.000 0.000 0.000  0.000 0.000 0.000 
3  0  0.000 0.000 0.000  0.000 0.000 0.000 

Le nombre donné dans la première ligne (-0,25) doit être inséré en tant que paramètre dans chacune des lignes de données. Puisque ce nombre varie dans chacun des centaines de fichiers, je ne peux pas le fournir comme un littéral.

J'ai écrit le programme sed suivant:

# Reduce line 1 to just a number. 
s/SLICE AT X= // 
# Store line 1 in hold space. 
1h 
# Clear the other header line. 
2d 
# Insert X coordinate from hold space. 
/^\ \{1,\}/G 
# Separate values with commas. 
s/\ \{1,\}/,/g 

Il obtient aussi loin que la production de ce:

-0.25 
,1,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25 
,2,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25 
,3,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25 
,4,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25 

Notez que la première ligne de la sortie est la première ligne d'origine.

Quelqu'un pourrait-il m'aider à obtenir le nombre collé dans le début de chaque ligne?

Merci à l'avance,

Ross

Répondre

1

-t-il être sed? Cela fait l'affaire pour moi:

$ perl -lane '$x=$1,next if m/^SLICE AT X= (.+)$/; next if $. == 2; print join "," => ($x, @F)' /tmp/so-1255443 
-0.25,1,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25,2,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25,3,0,0.000,0.000,0.000,0.000,0.000,0.000 
+0

Merci, Cela fait un excellent travail avec l'extrait fourni, mais se heurte à des problèmes avec plusieurs fichiers en entrée . Bien que chacun des fichiers utilise la même mise en page, la deuxième ligne s'insinue dans la sortie. Je me demande si cela pourrait être dû à la position de la ligne absolue? –

+0

$. n'est pas remis à zéro sur un nouveau fichier lors de l'utilisation de <>. voir eof dans la documentation de perlfunc –

+0

Merci. J'ai juste fini d'encapsuler l'appel perl dans un petit script shell, qui a fait l'affaire. Merci pour la pensée latérale. –

1

Notez que c'est vraiment mieux fait avec perl, mais voici une solution sed.

 
#!/usr/bin/sed -f 

# Reduce line 1 to just a number. 
s/SLICE AT X= // 
# Store line 1 in hold space. 
1h 
# Clear the other header line. 
1,2d 
# Insert X coordinate from hold space. 
x 
G 
# Separate values with commas. 
s/\ \{1,\}/,/g 
s/\n//g 
p 
s/\([^,]*\),.*/\1/ 
h 
d 

Le problème est que G ajoute l'espace d'attente, vous devez donc utiliser x d'abord pour échanger le motif et maintenir l'espace, ajoutez l'espace d'attente (qui était l'espace de travail), la sortie de votre ligne, puis restaurer l'espace de retenue. Vraiment, sed n'est pas le bon outil pour cela ...

2

Je suis d'accord avec William Pursell: vous n'avez pas atteint la limite de ce que cet outil peut faire, mais vous avez atteint la limite de ce qui doit être fait avec cet outil.

De toute façon, voici une autre approche, encore légèrement kludgey.


# Reduce line 1 to just a number. 
s/SLICE AT X= // 
# Store line 1 in hold space. 
1h 
# Clear the other header line. 
1,2d 
# Insert X coordinate from hold space. 
/^\ \{1,\}/G 
# The \n from line 1 tells me where to split/swap 
s/\(.*\)\n\(.*\)/\2\1/ 
# Separate values with commas. 
s/ \{1,\}/,/g
1

Vous pouvez utiliser awk pour de telles tâches. utiliser sed uniquement pour des tâches très simples.

awk '/SLICE AT X/{ num = $NF;print;next} 
NR>2{ 
    $(NF+1) = num  
    $1=$1  
}1' OFS="," file 

sortie

# more file 
SLICE AT X= -0.25 
    ELEM NO   XI-COORD    INWARD-NORMAL 
1  0  0.000 0.000 0.000  0.000 0.000 0.000 
2  0  0.000 0.000 0.000  0.000 0.000 0.000 
3  0  0.000 0.000 0.000  0.000 0.000 0.000 
# ./shell.sh 
SLICE AT X= -0.25 
    ELEM NO   XI-COORD    INWARD-NORMAL 
1,0,0.000,0.000,0.000,0.000,0.000,0.000,-0.25 
2,0,0.000,0.000,0.000,0.000,0.000,0.000,-0.25 
3,0,0.000,0.000,0.000,0.000,0.000,0.000,-0.25 
0

Cela pourrait fonctionner pour vous:

sed -i '1{s/.* //;h;d};2d;s/\s\+/,/g;G;s/\(.*\)\n\(.*\)/\2\1/' file 
-0.25,1,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25,2,0,0.000,0.000,0.000,0.000,0.000,0.000 
-0.25,3,0,0.000,0.000,0.000,0.000,0.000,0.000 
Questions connexes