awk bez wypisywania nowej linii

169

Chcę, aby zmienna suma / NR była drukowana obok siebie w każdej iteracji. Jak uniknąć wypisywania znaku nowej linii w każdej iteracji przez awk? W moim kodzie nowa linia jest drukowana domyślnie w każdej iteracji

for file in cg_c ep_c is_c tau xhpl
printf "\n $file" >> to-plot.xls
    for f in 2.54 1.60 800 
        awk '{sum+=$3}; END  {print  sum/NR}' ${file}_${f}_v1.xls >> to-plot-p.xls
    done
done

Chcę, aby wynik wyglądał tak

cg_c ans1  ans2  ans3  
ep_c ans1  ans2  ans3 
is_c ans1  ans2  ans3
tau  ans1  ans2  ans3 
xhpl ans1  ans2  ans3

moje obecne wyjście jest takie

**cg_c**
ans1
ans2
ans3
**ep_c**
ans1
ans2
ans3
**is_c**
ans1
ans2
ans3
**tau**
ans1
ans2
ans3
**xhpl**
ans1
ans2
ans3
Sharat Chandra
źródło

Odpowiedzi:

219

awk '{sum+=$3}; END {printf "%f",sum/NR}' ${file}_${f}_v1.xls >> to-plot-p.xls

printdomyślnie wstawi nowy wiersz. Nie chcesz, aby tak się stało, dlatego użyj printfzamiast tego.

CodeRain
źródło
4
Ale uwaga, która printfinterpretuje, %swięc używaj printf "%s" whateverzamiast printf whatever.
Matthieu,
1
printf "%s",whateverZapomniałeś o przecinku. Możesz także rozszerzyć o więcej zmiennych i oddzielić je przecinkami.
Hielke Walinga
74

Zmienna ORS (separator rekordów wyjściowych) w AWK ma wartość domyślną "\ n" i jest drukowana po każdym wierszu. Możesz zmienić to na „” w BEGINsekcji, jeśli chcesz, aby wszystko było drukowane po kolei.

danben
źródło
6
Możesz nawet chcieć ustawić to ""(bez spacji), aby w ogóle nie było separacji.
mschilli
8
W ten sposób:awk 'BEGIN {ORS="\t"} {sum+=$3}; END {print sum/NR}' ${file}_${f}_v1.xls >> to-plot-p.xls
Fredrik Erlandsson
2
Lub ORS="\r"jeśli chcesz np. Wydrukować licznik pokazujący postęp.
Skippy le Grand Gourou
47

Myślę, że wiele osób wchodzi w to pytanie, szukając sposobu na uniknięcie nowej linii awk. Dlatego mam zamiar zaproponować rozwiązanie tego problemu, ponieważ odpowiedź na konkretny kontekst została już rozwiązana!

W awk, printautomatycznie wstawia a ORSpo wydrukowaniu. ORSoznacza „output record separator” i domyślnie przyjmuje nową linię. Więc ilekroć powiesz, print "hi"awk wypisze „cześć” + nowa linia.

Można to zmienić na dwa różne sposoby: używając pustego ORSlub używając printf.

Korzystanie z pustego pliku ORS

awk -v ORS= '1' <<< "hello
man"

To zwraca „helloman”, wszystko razem.

Problem polega na tym, że nie wszystkie awks akceptują ustawienie pustego ORS, więc prawdopodobnie będziesz musiał ustawić inny separator rekordów.

awk -v ORS="-" '{print ...}' file

Na przykład:

awk -v ORS="-" '1' <<< "hello
man"

Zwraca „hello-man-”.

Używanie printf(preferowane)

Chociaż printzałącza się ORSpo płycie, printfnie. Dlatego printf "hello"po prostu drukuje „cześć”, nic więcej.

$ awk 'BEGIN{print "hello"; print "bye"}'
hello
bye
$ awk 'BEGIN{printf "hello"; printf "bye"}'
hellobye

Na koniec zwróć uwagę, że generalnie pomija to ostatnią nową linię, więc znak zachęty powłoki będzie w tej samej linii, co ostatnia linia wyniku. Aby to wyczyścić, użyj, END {print ""}aby nowa linia została wydrukowana po całym przetwarzaniu.

$ seq 5 | awk '{printf "%s", $0}'
12345$
#    ^ prompt here

$ seq 5 | awk '{printf "%s", $0} END {print ""}'
12345
fedorqui 'SO przestań szkodzić'
źródło
5

jednokierunkowa

awk '/^\*\*/{gsub("*","");printf "\n"$0" ";next}{printf $0" "}' to-plot.xls
ghostdog74
źródło
1
Moll uwaga: nigdy nie używać printf $0, ponieważ $0mogą zawierać ciągi jak %F, itp ... Po łatwo nie powiedzie się (przynajmniej z GAWK 3.1.5) echo "%F"|awk '{printf $0}'. Użyj printf "%s",$0zamiast tego.
Vlad
2

Możesz po prostu dynamicznie używać ORS w następujący sposób:

awk '{ORS="" ; print($1" "$2" "$3" "$4" "$5" "); ORS="\n"; print($6-=2*$6)}' file_in > file_out

Andrea Barletta
źródło
1

Jeśli Perl jest opcją, oto rozwiązanie na przykładzie fedorqui:

seq 5 | perl -ne 'chomp; print "$_ "; END{print "\n"}'

Objaśnienie:
chompusuwa
print "$_ "znak nowej linii drukuje każdy wiersz, dodając spację, w
której END{}blok jest używany do wydrukowania nowego wiersza

wynik: 1 2 3 4 5

Chris Koknat
źródło