Mengubah string multi-baris menjadi satu dipisahkan koma

95

Katakanlah saya memiliki string berikut:

something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

Bagaimana cara mengubahnya menjadi sederhana

+12.0,+15.5,+9.0,+13.5

dalam pesta?

Alex Coplan
sumber
Mari mundur sejenak dan anggap utas ini sebagai dakwaan mencolok tentang bash sebagai bahasa pemrograman. Pertimbangkan Scala's listOfStuff mkString ", ", atau Haskell'sintercalate ", " listOfString
FP Freely

Jawaban:

92

Anda dapat menggunakan awkdan sed:

awk -vORS=, '{ print $2 }' file.txt | sed 's/,$/\n/'

Atau jika Anda ingin menggunakan pipa:

echo "data" | awk -vORS=, '{ print $2 }' | sed 's/,$/\n/'

Untuk memecahnya:

  • awk sangat bagus dalam menangani data yang dipecah menjadi beberapa bidang
  • -vORS=,setel "pemisah rekaman keluaran" ke ,, yang Anda inginkan
  • { print $2 }memberitahu awkuntuk mencetak bidang kedua untuk setiap catatan (baris)
  • file.txt adalah nama file Anda
  • sedhanya menghilangkan trailing ,dan mengubahnya menjadi baris baru (jika Anda tidak menginginkan baris baru, Anda bisa melakukannya s/,$//)
Dan Fego
sumber
1
awk: opsi -v tidak valid :(
Marsellus Wallace
6
Tambahkan spasi antara -v dan ORS =, (untuk saya, di osx)
Graham P Heath
Bagaimana cara melakukan perintah yang sama untuk memisahkan pipa? awk -v ORS=| '{ print $1 }' DCMC.rtf | sed 's/,$/\n/'saya mendapatkan kesalahan
Yogesh
2
anehnya, ketika saya mencoba melakukan ini, hasilnya kosong.
eternaltyro
1
Saya pikir untuk versi perpipaan seharusnya {print $1}sebaliknya saya hanya mendapatkan koma dalam keluaran
Przemysław Czechowski
162

Bersih dan sederhana:

awk '{print $2}' file.txt | paste -s -d, -
Mattias Ahnberg
sumber
3
Ini adalah jawaban terbaik di sini, dan jelas cara yang benar untuk melakukannya
forresthopkinsa
Bagaimana cara mengutip setiap nilai dengan tanda kutip tunggal / ganda?
Hussain
1
@Hussaincat thing | awk -F',' '{ print "'\''" $7 "'\' '" }' | paste -s -d ','
starbeamrainbowlabs
Bagaimana digunakan ,'sebagai pembatas?
Kasun Siyambalapitiya
Ingatlah untuk menangani baris baru Windows (misalnya menggunakan dos2unix) jika ada CRLF dalam string tersebut.
Bowi
19
cat data.txt | xargs | sed -e 's/ /, /g'
Bhargav Srinivasan
sumber
10
$ awk -v ORS=, '{print $2}' data.txt | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5
kev
sumber
cheers, bagaimana jika input ke awk melalui input standar (masukkan saja ke function | awk...dalam contoh anda?
Alex Coplan
10

awk satu kapal

$ awk '{printf (NR>1?",":"") $2}' file

+12.0,+15.5,+9.0,+13.5
Rahul Verma
sumber
8

Ini harus bekerja juga

awk '{print $2}' file | sed ':a;{N;s/\n/,/};ba'
jaypal singh
sumber
8

Ini mungkin berhasil untuk Anda:

cut -d' ' -f5 file | paste -d',' -s
+12.0,+15.5,+9.0,+13.5

atau

sed '/^.*\(+[^ ]*\).*/{s//\1/;H};${x;s/\n/,/g;s/.//p};d' file
+12.0,+15.5,+9.0,+13.5

atau

sed 's/\S\+\s\+//;s/\s.*//;H;$!d;x;s/.//;s/\n/,/g' file

Untuk setiap baris dalam file; potong bidang pertama dan spasi setelahnya, potong sisa baris setelah bidang kedua dan tambahkan ke ruang tunggu. Hapus semua baris kecuali yang terakhir tempat kita menukar ke ruang tunggu dan setelah menghapus baris baru yang diperkenalkan di awal, ubah semua baris baru menjadi ,.

NB Bisa ditulis:

sed 's/\S\+\s\+//;s/\s.*//;1h;1!H;$!d;x;s/\n/,/g' file
potong
sumber
4

Anda dapat menggunakan grep:

grep -o "+\S\+" in.txt | tr '\n' ','

yang menemukan string dimulai dengan +, diikuti dengan string apa pun \S\+, lalu mengubah karakter baris baru menjadi koma. Ini seharusnya cukup cepat untuk file besar.

kenorb
sumber
4

Coba kode mudah ini:

awk '{printf("%s,",$2)}' File1
Vonton
sumber
3

coba ini:

sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*"\1,"'
sedClearLastComma='s"\(.*\),$"\1"'
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"

hal baiknya adalah bagian yang mudah dari menghapus karakter "\ n" baris baru!

EDIT: cara hebat lain untuk menggabungkan garis menjadi satu baris dengan sed adalah ini: |sed ':a;N;$!ba;s/\n/ /g'dapatkan dari sini .

Kekuatan Aquarius
sumber
EDIT itu luar biasa - +1!
JoeG
2

Solusi yang ditulis dalam Bash murni:

#!/bin/bash

sometext="something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)"

a=()
while read -r a1 a2 a3; do
    # we can add some code here to check valid values or modify them
    a+=("${a2}")
done <<< "${sometext}"
# between parenthesis to modify IFS for the current statement only
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}")

Hasil: + 12.0, + 15.5, + 9.0, + 13.5

Quatro oleh Quatro
sumber
2

Jangan melihat solusi sederhana ini dengan awk

awk 'b{b=b","}{b=b$2}END{print b}' infile
ctac_
sumber
0

Dengan perl:

fg@erwin ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
EOF

+12.0,+15.5,+9.0,+13.5
fge
sumber
0

Anda juga dapat melakukannya dengan dua panggilan sed:

$ cat file.txt 
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta'
+12.0,+15.5,+9.0,+13.5

Panggilan sed pertama menghapus data yang tidak menarik, dan yang kedua menggabungkan semua baris.

Elias Dorneles
sumber
0

Anda juga dapat mencetak seperti ini:

Just awk: menggunakan printf

bash-3.2$ cat sample.log
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

bash-3.2$ awk ' { if($2 != "") { if(NR==1) { printf $2 } else { printf "," $2 } } }' sample.log
+12.0,+15.5,+9.0,+13.5

sumber
0

Solusi Perl lainnya, mirip dengan awk Dan Fego:

perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'

-a memberi tahu perl untuk membagi baris input menjadi larik @F, yang diindeks mulai dari 0.

Chris Koknat
sumber
0

Bagian tersulit mungkin adalah memilih "kolom" kedua karena saya tidak tahu cara mudah untuk memperlakukan banyak spasi sebagai satu. Selebihnya mudah saja. Gunakan substitusi bash.

# cat bla.txt
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

# cat bla.sh
OLDIFS=$IFS
IFS=$'\n'
for i in $(cat bla.txt); do
  i=$(echo "$i" | awk '{print $2}')
  u="${u:+$u, }$i"
done
IFS=$OLDIFS
echo "$u"

# bash ./bla.sh
+12.0, +15.5, +9.0, +13.5
Marki
sumber