Jak mogę „scalić” wzory w jednym wierszu?

10

Robię grep i sed i otrzymuję 2 wiersze pliku, który mnie interesuje. Jak mogę uzyskać te wiersze w jednym wierszu kończącym się nowym znakiem wiersza?
Teraz dostaję:

pattern1  
pattern2  

chciałbym dostać pattern1 pattern2 \n

Jim
źródło
1
Czy możesz udostępnić więcej przykładowych danych?
slm
Użyj printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'
Valentin Bajrami,
Wklej to narzędzie do zadania, jeśli zamierzasz scalić wiele wierszy wyników w jeden.
slm
jakieś konkretne narzędzie? Jak zamierzasz to zrobić?
Braiam

Odpowiedzi:

7

paste:

{...pipeline...} | paste -d " " - -

To znaczy: „przeczytaj wiersz ze standardowego wejścia (pierwszy -), przeczytaj kolejny wiersz ze standardowego wejścia (drugi -), a następnie połącz je spacją”


technika specyficzna dla bash:

$ x=$(grep -o pattern. test.txt)
$ echo "$x"
pattern1
pattern2
$ mapfile -t <<< "$x"
$ echo "${MAPFILE[*]}"
pattern1 pattern2

ref: http://www.gnu.org/software/bash/manual/bashref.html#index-mapfile

Glenn Jackman
źródło
Co to jest - -? Czy takie polecenie jest takie?
Jim
@Jim - tak, to prawda. Mówią, pastejak chcesz przetwarzać dane wejściowe. 2 na raz. Dodaj więcej do zrobienia 3 naraz. seq 10 | paste -d " " - - .
slm
6

Umieszczę trzy wersje różnych metod pod rząd

AWK

printf %s\\n pattern1 pattern2 | awk -vRS="\n" -vORS=" " '1; END {print RS}'

SED

printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'

TR

printf %s\\n pattern1 pattern2 | tr '\n' ' '; echo

I jest ich o wiele więcej.

Valentin Bajrami
źródło
trRozwiązanie będzie przełknąć przełamane kończy, więc może warto dodać ; echodo tego jednego
Glenn Jackman
@glennjackman ah racja! Dzięki za podpowiedź. Możesz jednak zmienić odpowiedź. Trochę mi tego brakowało!
Valentin Bajrami
2

możesz to zrobić za pomocą skryptu powłoki lub w wierszu poleceń, po prostu umieść dane wyjściowe polecenia w zmiennej, a następnie echo:

# x=$(grep -e "pattern1\|pattern2" test)
# printf '%s\n' "$x"
pattern1 pattern2
Nidal
źródło
bez cudzysłowu, zmienna podlega również rozszerzaniu nazw plików, więc jeśli w wyniku są jakieś znaki globu (jak *lub ?), wartości mogą ulec zmianie.
glenn jackman
@glennjackman, dziękuję za wzmiankę o tym, jak możemy to naprawić?
Nidal
@Networker nie używając backticków, ale $()zamiast tego… i używając printfprintf '%s\n' "$x"
Valentin Bajrami
Spodziewałbym się, że printf '%s\n' "$x"NIE usunie to „wewnętrznej” nowej linii.
glenn jackman
2

Za pomocą sedmożesz to zrobić:

<your previous commands> | sed '{N; s/\n/ /}'
  • N;mówi, sedaby dodać następny wiersz do obszaru wzorów, więc teraz seddziała z obiema liniami.
  • s/\n/ / zamienia znak nowej linii spacją, „łącząc” dwie linie razem.
Alaa Ali
źródło
2

Prosty sposób, wyjście rury do xargs:

$ echo -e 'a\nb' | xargs
a b

Działa to tylko z niewielkim wyjściem, ponieważ jest ograniczone maksymalną liczbą znaków w wierszu poleceń. Największa wartość zależy od systemu, możesz uzyskać tę wartość za pomocą getconf ARG_MAX.

Cuonglm
źródło
1
( set -f; IFS='
'; printf '%s %s\n' $(grepcmd <input)
) >output

IFS chętnie je zje, jeśli chcesz.

mikeserv
źródło
-1

zawiń swój sed / grep w backtyki

kiedy twoje pierwotne polecenie było:

grep -i 'foo' mylog.log | sed 's/bar/baz/gi'

twoje nowe polecenie będzie:

`grep -i 'foo' mylog.log | sed 's/bar/baz/gi'`

Nie wprowadza odstępów między liniami, ale zawsze możesz przyczepić się do innej rury sed:

 | sed 's/$/ /'
TheRuss
źródło
1
O nie. Spowoduje to wykonanie wyniku polecenia sed.
glenn jackman