2010-03-18 17 views
8

mam ten przypadek użycia pliku XML z wejściem jakŁączenie wielu linii w jedną linię

Input: 
<abc a="1"> 
    <val>0.25</val> 
</abc> 
<abc a="2"> 
    <val>0.25</val> 
</abc> 
<abc a="3"> 
    <val>0.35</val> 
</abc> 
... 

Output: 
<abc a="1"><val>0.25</val></abc> 
<abc a="2"><val>0.25</val></abc> 
<abc a="3"><val>0.35</val></abc> 

mam około 200K wiersze w pliku w formacie wejściowe, w jaki sposób można szybko przekonwertować to do formatu wyjściowego .

Odpowiedz

3

w vim można zrobić z

:g/<abc/ .,/<\/abc/ join! 

Normalnie: przyłączyć doda miejsca w koniec każdej linii przed dołączeniem, ale ! to tłumi.

Generalnie polecam używanie odpowiedniej biblioteki do analizy XML w języku takim jak Python, Ruby lub Perl do manipulowania plikami XML (polecam Python + ElementTree), ale w tym przypadku łatwo jest uciec przy użyciu rozwiązanie regex.

+0

Dziękujemy! Właśnie tego potrzebowałem! –

+0

Mam podobne rozwiązanie, ponieważ pozostaną spacje między> i < ': g/val/norm kJxJx' ale jeśli nie masz nic przeciwko temu, po prostu wykonaj: ' g/val/norm kJJ' – SergioAraujo

0

nieelegancka jedna linijka, która powinna wystarczyć, choć niezbyt szybko.

cat file | perl -e ' 
    $x=0; 
    while(<>){ 
     s/^\s*(\S*(?:\s+\S+)*)\s*$/$1/g; 
     print; 
     $x++; 
    if($x==3){ 
     print"\n"; 
     $x=0; 
    } 
}' > output 
+0

Zamiast 'cat file', wystarczy użyć' Arkku

+0

@Arkku - będzie działać równie dobrze. To mój stary nawyk, a ja jestem bardziej zadowolony z cat $ FILE | – zellio

+0

Wystrzeliwuje jednak bezużyteczny "kot". W niektórych bardzo ograniczonych systemach istnieje niski limit liczby jednoczesnych procesów, które są liczone. Ponadto może to być znaczące spowolnienie, jeśli sam proces jest szybkim czytnikiem, np. spróbuj 'cat/dev/zero | dd bs = 1k count = 1000' vs 'dd bs = 1k count = 1000 Arkku

0

Można to zrobić:

perl -e '$i=1; while(<>){chomp;$s.=$_;if($i%3==0){$s=~s{>\s+<}{><};print "$s\n";$s="";}$i++;}' file 
+0

chomp nie jest dobry, ponieważ pozostawia zbyt wiele białych znaków, chyba że nasz pytający jest w porządku z tym. – zellio

+0

@Mimisbrunnr: jeśli uważnie patrzysz, używam wyrażenia regularnego, aby pozbyć się dodatkowych spacji. – codaddict

+0

Przepraszam, mówiłem przed całkowitym przeczytaniem twojego kodu. – zellio

1
$ awk ' 
    /<abc/ && NR > 1 {print ""} 
    {gsub(" +"," "); printf "%s",$0} 
' file 
<abc a="1"> <val>0.25</val></abc> 
<abc a="2"> <val>0.25</val></abc> 
<abc a="3"> <val>0.35</val></abc> 
+0

+1 Będziesz także potrzebować: 'END {print" "}', aby upewnić się, że plik kończy się znakiem nowej linii. –

0
sed '/<abc/,/<\/abc>/{:a;N;s/\n//g;s|<\/abc>|<\/abc>\n|g;H;ta}' file 
0
tr "\n" " "<myfile|sed 's|<\/abc>|<\/abc>\n|g;s/[ \t]*<abc/<abc/g;s/>[ \t]*</></g' 
1

Bash:

while read s; do echo -n $s; read s; echo -n $s; read s; echo $s; done < file.xml 
1

można zapisywać makra. Zasadniczo, co powinienem zrobić, to zacząć od kursora na początku pierwszej linii. Naciśnij "qa" (zapisuje makro do rejestru). Przesunięcie prasy-V do liniowego trybu wizualnego. Następnie wyszukaj tag końcowy "// abc". Następnie naciśnij shift-J, aby dołączyć do linii. Następnie musisz przesunąć kursor do następnej zakładki, prawdopodobnie za pomocą "j ^" i naciśnij "q", aby zatrzymać nagrywanie. Możesz ponownie uruchomić nagranie za pomocą "@a" lub określić 10000 @ a, jeśli chcesz. Jeśli tagi są różne lub nie, to po prostu musisz zmienić sposób otwierania i zamykania tagów w wyszukiwaniach lub coś w tym stylu.

+0

Oczywiście to jest oparte na vimie rozwiązanie ... –

4

W vim:

  • pozycji na pierwszej linii
  • qq: rozpocząć nagrywanie makra
  • gJgJ: łączy dwie kolejne linie bez dodawania spacji
  • j: zejść
  • q: stop nagranie
  • [email protected]: N = Liczba linii (w rzeczywistości około 1/3 wszystkich linii, ponieważ się skondensowanych w podróży)
+0

Po 'gJgJ', nie jest konieczne dla' j'. – systemovich

0

To powinno działać w trybie Ex:

:%s/\(^<abc.*>\)^M^\(.*\)^M^\(^<\/abc>\).*^M/\1\2\3^M/g

powinienem mieć dodatkowe spacje (lub tab pomiędzy wartością), ale możesz ją usunąć w zależności od tego, co to jest (\ t lub \ \ \ \).

Co szukasz/wymiana jest tutaj (wzorzec1) [Enter] (pattern2) [Enter] (pattern3) [enter] i zastąpienie go (WZÓR 1) (pattern2) (pattern3) [ENTER]

^M odbywa się za pomocą Ctrl + v Ctrl + M

1
sed '/^<abc/{N;N;s/\n\| //g}' 

# remove \n or "space" 
# Result 

<abca="1"><val>0.25</val></abc> 
<abca="2"><val>0.25</val></abc> 
<abca="3"><val>0.35</val></abc> 
Powiązane problemy