Mam plik .csv (na komputerze Mac), który ma kilka pustych linii, np .:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
Które chcę przekonwertować na:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
Wiem, że musi być jeden liniowiec, ale nie znam awk ani sed. Wszelkie wskazówki bardzo mile widziane!
shell
text-processing
sed
awk
pitosalas
źródło
źródło
Odpowiedzi:
-v
Aby to zrobić, możesz użyć trybu grep (dopasowanie odwrócone):Pamiętaj, że muszą to być różne pliki, ze względu na działanie przekierowań powłoki. Plik wyjściowy jest otwierany (i opróżniany) przed odczytaniem pliku wejściowego. Jeśli masz moreutils (domyślnie nie w systemie Mac OS X), możesz skorzystać
sponge
z obejścia tego:Ale oczywiście trudniej jest wrócić, jeśli coś pójdzie nie tak.
Jeśli „puste wiersze” faktycznie mogą zawierać spacje (brzmi jak one), możesz zamiast tego użyć tego:
To zignoruje puste linie, a także linie zawierające tylko białe znaki. Możesz oczywiście wykonać na nim tę samą
sponge
transformację.źródło
egrep -v '^[[:space:]]*$'
... uwaga grep -> egrep i dziwny nowy wzóriconv -f utf16le file.csv | head
lubiconv -f utf16be file.csv | head
Najłatwiejsza opcja jest właśnie
grep .
. Tutaj kropka oznacza „dopasuj wszystko”, więc jeśli linia jest pusta, nie jest dopasowana. W przeciwnym razie drukuje całą linię bez zmian.źródło
Aby usunąć puste linie na miejscu za pomocą ksh93:
<>;
Operatorem przekierowania jest specyficzna ksh93 i jest taka sama jak standardowego<>
operatora tą różnicą, że obcina ksh plik po komendzie został zakończony.sed '/./!d'
jest skomplikowanym sposobem pisaniagrep .
, ale niestety GNU grep przynajmniej narzeka, jeśli jego stdout wskazuje ten sam plik co stdin. Powiedziałbyś, że można napisać:Ale niestety jest błąd w ksh93 (przynajmniej moja wersja (93u +)), w tym przypadku plik wydaje się w tym przypadku obcięty do zera.
Wygląda na to, że omija ten błąd, ale teraz jest znacznie bardziej skomplikowany niż polecenie sed.
źródło
awk '/./' file 1<>; file
który zadziałał. Dla mnie to jeszcze wyraźniejsze niżsed '/./!d'
Oto
Perl
jedna linijka:EDYCJA: Ulepszony kod oparty na komentarzach ruakh poniżej.
źródło
perl -ni -e '/./ and print' yourfile
$
jest kotwicą (tj. o zerowej szerokości), więc wyklucza nową linię. Co do zbędnej przestrzeni, to jest powód, dla którego dodałem/x
, że nie chcęPerl
próbować interpolować „$ \” w wyrażeniu regularnym$
, biorąc pod uwagę, że masz\n
. (Alternatywnie - nie potrzebujesz\n
, biorąc pod uwagę, że masz\s*
i$
, ale myślę, żes/^\s*\n//
wyjaśnia, że nowa linia jest usuwana.) Nie potrzebujesz również/m
; nie ma to wpływu na to polecenie. A kiedy pozbędziesz$
się przestrzeni i przestrzeni, nie będziesz jej potrzebować/x
.\n
Sam można usunąć; czego nie można zrobić, to usunąć zarówno$
i\n
.s/^\s*//
Miałby więc problem, który opisujesz, ales/^\s*$//
byłby w porządku, z powodu\s*
i$
. (Czy rozumiesz, co mam na myśli?)$
że dopasuje się przed nową linią (pod warunkiem, że/m
flaga jest włączona, albo nowa linia jest ostatnim znakiem ciągu lub obydwoma), ale może także pasować do końca łańcucha. Na przykład"abc" =~ m/^abc$/
prawda. W przypadku\s*$
,\s*
jest chciwy co jeść aż do nowej linii, a następnie$
dopasowuje koniec-of-string. (Ale myślę, żes/^\s*\n//
i tak jest jaśniejsze, więc twoja odpowiedź jest w porządku, tak jak jest teraz.)W oparciu o wyjaśnienie w komentarzach do twojego pytania, coś takiego:
może robić co chcesz.
Pusty separator rekordów jest specjalnym przypadkiem, który mówi,
awk
że rekordy mają być akapitami (oddzielonymi sekwencjami pustych linii). Ustawienie separatora rekordów wyjściowych również na pusty ciąg oznacza, że treść tych akapitów (bez separatorów) należy połączyć.1
jest tylko prawdziwym warunkiem wydrukowania każdego rekordu.Pominąłoby to jednak końcowy znak nowej linii, dzięki czemu można wykonać:
źródło
Wiem, że byłoby łatwiej, gdybym dał plik, ale niestety zawierał poufne informacje, których nie mogłem udostępnić. W międzyczasie napisałem mi skrypt rubinowy, który wydawał się załatwić sprawę:
Dziękujemy wszystkim za pomoc!
źródło
produkuje
źródło
Znalazłem pomysł na możliwe rozwiązanie dotyczące przepełnienia stosu .
sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv
Prawdopodobnie powinieneś wykonać kopię zapasową pliku csv przed przetestowaniem go, ale przynajmniej w podanym przykładzie działa on bezbłędnie.
Odpowiednie wyjaśnienie na temat wewnętrznego działania tego wyrażenia znajduje się w odpowiedzi, właśnie go edytowałem, aby wyszukać linie, które nie kończą się znakiem
"
([^"]\n
).źródło
Jeśli z własnej odpowiedzi chcesz usunąć znaki nowej linii zawarte w ciągach cytowanych, możesz:
Możesz także użyć
-i
flagi perla do edycji plików na miejscu .Lub z GNU awk:
lub:
(jeśli walczysz o najkrótszą)
Zauważ, że te zakładają, że nie są tam uciekł podwójnych znaków cudzysłowu w wejściu.
źródło
Wygląda na to, że chcesz więcej niż usuwanie pustych linii, ale usuń każdą sekwencję 2 lub więcej znaków nowej linii.
Co możesz zrobić z perlem:
Możesz także użyć
-i
flagi perla do edycji plików na miejscu .źródło
Istnieje coraz krótszy sposób usuwania pustych linii w
AWK
:awk 'NF' file
Ale aby uzyskać pożądany wynik, wystarczy jeden prosty linijka:
awk 'NF {printf("%s ", $0); i++;} !(i % 2) {printf("\n");}' file
Wyjaśnienie
W
AWK
pusta linia oznacza, że wiersz / rekord nie ma pól, co oznacza, żeNF
zmienna (Number of Fields) ma wartość zero. Jedna linijka powyżej zostanie wykonana tylko podczasNF > 0
drukowania wszystkich linii, ale pustych.i++
Jest niepusty linie licznik.!(i % 2)
Jest stosowany w celu wydrukowania dwa kolejne niepuste linie na drodze żądanego wyjścia, to znaczy za każdym razem wielokrotnością 2 zostanie znaleziony,modulo
rachunku!(i % 2)
rentowności 1, co kończy konkatenacji dwóch niepustych wierszy.źródło
Możesz używać Vima w trybie Ex:
v/./
znajdź puste linied
kasowaćx
Zapisz i zamknijźródło