2016-05-03 6 views
-1

Ich habe eine große TXT-Datei, die ich in der Pipeline bearbeiten möchte. Aber an derselben Stelle in der Pipeline möchte ich die Anzahl der Zeilen in der Variable $ nol setzen. Ich will nur sintax sehen, wie könnte ich Variable in der Pipeline wie gesetzt:Ist es möglich, Variable in der Pipeline zu setzen?

cat ${!#} | tr ' ' '\n'| grep . ; $nol=wc -l | sort | uniq -c ... 

Das nach dem zweiten Rohr sehr falsch ist, aber wie kann ich es in der Bash?

Eine der Lösungen ist:

nol=$(cat ${!#} | tr ' ' '\n'| grep . | wc -l) 
pipeline all from the start again 

aber ich will nicht Skript die gleiche Sache zweimal tun, bec Ich habe mehr Rohre hier dann.

I awk oder sed verwenden musn't ...

+0

Was genau möchten Sie tun? Für mich sieht es so aus als könnte 'awk' es in einem Schuss tun. – fedorqui

+0

Ich darf nicht awk oder sed. –

+2

Immer noch: vielleicht kann Bash allein damit umgehen. Versuchen Sie, das Gesamtbild zu geben, weil Ihre Fragen ziemlich lokalisiert sind und möglicherweise ein konzeptionelles Problem verbergen. Es sieht auch so aus, als ob die Ausgabe bis zu einer bestimmten Pipe in einer Variablen gespeichert werden kann. Zählen Sie dann Zeilen und Echo plus Pipe zu den restlichen Befehlen. – fedorqui

Antwort

1

können Sie einen tee verwenden und dann schreiben Sie es in eine Datei, die Sie später verwenden:

tempfile="xyz" 
tr ' ' '\n' < "${!#}" | grep '.' | tee > "$tempfile" | sort | uniq -c ... 
nol=$(wc -l "$tempfile") 

Oder man kann es in die andere Richtung benutzen um:

nol=$(tr ' ' '\n' < "${!#}" | grep '.' \ 
    | tee >(sort | uniq -c ... > /dev/tty) | wc -l 
1

Sie eine Variable in einem bestimmten Link einer Pipeline gesetzt, aber das ist nicht sehr sinnvoll, da nur diese bestimmte Verbindung wird davon betroffen sein.

Ich empfehle, einfach eine temporäre Datei zu verwenden.

set -e 
trap 'rm -f "$tmpf"' EXIT 
tmpf=`mktemp` 
cat ${!#} | tr ' ' '\n'| grep . | sort > "$tmpf" 
nol="$(wc "$tmpf")" 
< "$tmpf" uniq -c ... 

Sie können die temporäre Datei mit T-Shirt und einer Named Pipe vermeiden, aber es wird wahrscheinlich viel besser nicht durchführen (es kann sogar schlechter ab).

1

Sieht für mich so aus, als würden Sie fragen, wie Sie vermeiden können, zweimal durch die Datei zu gehen, nur um die Anzahl der Wörter und Zeilen zu ermitteln.

Mit Bash können Sie Variablen lesen, und wc kann alle benötigten Zahlen auf einmal erzeugen.

NAME 
    wc -- word, line, character, and byte count 

So zu beginnen ...

read words line chars < <(wc < ${!#}) 

Diese füllt die drei Variablen basierend auf einer Eingabe von process substitution erzeugt.

Aber Ihre Frage enthält eine weitere Teil-Befehlszeile, die ich denke, Sie beabsichtigen, wie:

nol=$(sort -u ${!#} | wc -l) 

Diese aus der Wortanzahl des ersten Befehlszeile deutlich anders sind, so dass Sie nicht eine einzige wc Instanz verwenden können um beides zu erzeugen. Stattdessen könnte eine Option sein, Ihre Funktionalität in ein Skript zu setzen, die auf einmal beide Funktionen hat:

read words uniques < <(
awk ' 
     { 
     words += NF 
     for (i=1; i<=NF; i++) { unique[$i] } 
     } 
     END { 
     print words,length(unique) 
     } 
    ' ${!#} 
) 
+0

'$ {#!}' Meinst du das? – 123

+0

@ 123 - guter Fang, danke. – ghoti

1

UPDATE:

Nahm eine Minute, aber ich habe es ...

cat ${!#} | tr ' ' '\n'| tee >(nol=$(wc -l)) | sort | uniq -c ... 

Zurück:

Die einzige Möglichkeit, die ich denken kann, dies zu tun in Variablen speichert und ruft zurück. Sie würden den Befehl nicht mehr als einmal ausführen. Sie würden nur die Ausgabe in Variablen auf dem Weg speichern.

aCommand=($(cat ${!#} | tr ' ' '\n'));sLineCount=$(echo ${#aCommand[@]});echo ${aCommand[@]} | sort | uniq -c ... 
  • aCommand wird die Ergebnisse des ersten Satzes von Befehlen, die in einem Array gespeichert
  • sLineCount wird
  • die Elemente (Zeilen) in dem Array zählen; ... Echo der Array-Elemente und weiter die Befehle von dort.