Comment puis-je «fusionner» des motifs sur une seule ligne?

10

Je fais grep et sed et j'obtiens 2 lignes d'un fichier qui m'intéresse. Comment puis-je obtenir ces lignes sur une seule ligne se terminant par le nouveau caractère de ligne?
Maintenant je reçois:

pattern1  
pattern2  

Je voudrais obtenir pattern1 pattern2 \n

Jim
la source
1
Pouvez-vous partager davantage d'exemples de données?
slm
Utilisation printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'
Valentin Bajrami
Le collage est l'outil pour le travail, si vous avez l'intention de fusionner plusieurs lignes de sortie en une seule.
slm
un outil spécifique? Comment comptez-vous y parvenir?
Braiam

Réponses:

7

paste:

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

Cela dit: "lire une ligne de stdin (le premier -), lire une autre ligne de stdin (le second -), puis les joindre avec un espace"


une technique spécifique à bash:

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

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

glenn jackman
la source
Qu'est-ce que c'est - -? La commande est-elle comme ça?
Jim
@Jim - oui c'est vrai. Ceux-ci indiquent pastecomment vous souhaitez qu'il traite l'entrée. 2 à la fois. Ajoutez-en plus pour faire 3 à la fois. seq 10 | paste -d " " - - .
slm
6

Je vais mettre trois versions différentes méthodes d'affilée

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

Et il y en a beaucoup plus.

Valentin Bajrami
la source
La trsolution engloutira la nouvelle ligne de fin, donc vous voudrez peut-être ajouter ; echoà celle-ci
glenn jackman
@glennjackman ah à droite! Merci pour l'astuce. Vous êtes cependant libre de modifier la réponse. J'ai raté ce morceau!
Valentin Bajrami
2

vous pouvez le faire en utilisant le script shell ou en ligne de commande, mettez simplement la sortie de la commande dans une variable puis echoelle:

# x=$(grep -e "pattern1\|pattern2" test)
# printf '%s\n' "$x"
pattern1 pattern2
Nidal
la source
sans guillemets, la variable est également soumise à l'expansion du nom de fichier, donc si vous avez des caractères globaux (comme *ou ?) dans le résultat, les valeurs peuvent changer.
glenn jackman
@glennjackman, merci de le mentionner, comment pouvons-nous résoudre ce problème?
Nidal
@Networker en n'utilisant pas de backticks mais à la $()place .. et en utilisant printfprintf '%s\n' "$x"
Valentin Bajrami
Je m'attends à ce que printf '%s\n' "$x"cela ne supprime PAS la nouvelle ligne "interne".
glenn jackman
2

Avec sed, vous pouvez faire ceci:

<your previous commands> | sed '{N; s/\n/ /}'
  • N;indique sedd'ajouter la ligne suivante dans l'espace de motif, donc sedtravaille maintenant avec les deux lignes.
  • s/\n/ / remplace le caractère de nouvelle ligne par un espace, "fusionnant" les deux lignes ensemble.
Alaa Ali
la source
2

Un moyen simple de diriger la sortie vers xargs:

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

Cela ne fonctionne qu'avec de petites sorties, car il est limité par le nombre maximum de caractères par ligne de commande. La plus grande valeur dépend du système, vous pouvez obtenir cette valeur en utilisant getconf ARG_MAX.

cuonglm
la source
1
( set -f; IFS='
'; printf '%s %s\n' $(grepcmd <input)
) >output

IFS se fera un plaisir de le manger si vous le souhaitez.

mikeserv
la source
-1

envelopper votre sed / grep dans des crochets

lorsque votre commande d'origine était:

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

votre nouvelle commande serait:

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

N'obtient pas les espaces entre les lignes, mais vous pouvez toujours virer de bord sur un autre tuyau sed:

 | sed 's/$/ /'
TheRuss
la source
1
Euh non. Cela exécutera la sortie de la commande sed.
glenn jackman