• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[solv] herausfinden, ob ein Skript per Pipe aufgerufen wurde

OsunSeyi

Hacker
Hi
Denkbar wäre
Code:
VALUES=`cat -`
Wenn $VALUES dann leer ist, weil keine Werte per Pipe übergeben wurde, soll statt dessen die Zwischenablage ausgelesen werden (VALUES=`xsel -p`).

Das Problem ist aber, daß das Script bei "cat -" quasi stehen bleibt, wenn es nicht per Pipe aufgerufen wurde.
Das Script müsste also "merken", ob es über eine Pipe oder ganz normal aufgerufen wird!

Code:
> echo '123' | script
   oder:
> script

Ich hoffe, mich verständlich ausgedrückt zu haben...
Ist das irgendwie zu realisieren?

viele Grüße
tom
 
A

Anonymous

Gast
Bei Einzelwörtern/Einzelwerten/.....usw geht sowas zB über einen Timeout bei read.
Code:
#!/bin/bash
read -t1 DATA
if [ -z $DATA ] ; then DATA=$(xsel -p) ;fi
echo $DATA
# echo testparameter | ./script.sh
testparameter
# ./script.sh
Ich komme aus der X-Zwischenablage
#
Wenn du mehrere mit Leerzeichen, Tabulator oder Zeilensprung getrennte Dinge auf diese Weise im Script verarbeiten willst, musste man das recht kompliziert und wohl sehr individuell ausfeilen. Da die Eingaben aus xsel dann wohl auch noch überprüft werden müssten, ob das überhaupt irgendwas Sinnvolles sein könnte was das Script verarbeiten kann ......

robi
 
OP
OsunSeyi

OsunSeyi

Hacker
Vielen Dank, das ist genau das gesuchte!
Im Fall "cat file | skript" kann das als Test verwendet werden, ob das Skript via Pipe aufgerufen wurde oder nicht.
:)

Code:
#	Teste auf Werteübergabe per Pipe:
	read -t 0.1 TEST
	if [ -z "$TEST" ] ; then

		VAL=`	xsel -p						|\
			awk 'BEGIN { FS = "\t" }
				   { print $'$COLUMN'  }'`

		NUM=`echo $VAL | sed 's| \+|+|g' | sed 's|+-|-|g'`

	else
		VAL=`	awk 'BEGIN { FS = "\t" }
				   { print $'$COLUMN'  }'`

		NUM=`echo $VAL | sed 's| \+|+|g' | sed 's|+-|-|g'`
	fi
echo 'scale=2; '$NUM | bc

Zum Berechnen von Zahlenwerten in einer vorgegebenen Spalte entweder einer ganzen Datei (echo file | skript) oder nur eines markierten Teilbereiches (skript). Das Ganze ist natürlich länger, und man könnte es sicher auch anders realisieren. Aber so ist es für mich am leichtesten zu merken...
 
OP
OsunSeyi

OsunSeyi

Hacker
Der zweite Weg (tty prüfen) ist bei 'gepipten' Dateien, die mit einer Leerzeile beginnen, anscheinend der funktionierendere Weg.
Auch 'egrep [[:graph:]] | read TEST' bringt seltsamerweise eine leere Variable!
 

abgdf

Guru
Immer machst Du so komische Sachen. ;) Ich bin ziemlich sicher, daß Du das, was Du eigentlich erreichen willst, auch eleganter hinbekommen könntest, ohne zu prüfen, ob da eine Pipe im Spiel war oder nicht.
 
OP
OsunSeyi

OsunSeyi

Hacker
Das ist zum Ausrechnen von Spalten in Abrechnungsdateien und kann auf alle möglichen Arten eingesetzt werden.
Da sind zB zwei Zeilen markiert, und 'summe -1' rechnet die erste Spalte.

'cat 0-Gelder | summe -1' rechnet die ganze Datei.

Natürlich geht das auch anders (vie zB Option -c wie Clipboard), aber so ist es total simpel.
Einfach etwas markieren und 'summe' eingeben, klappt meistens auch.
Dann wir alles, was nicht [[:summe:]]+(\.[[:summe:]]{2})? ist, und in einer eigenen Spalte steht, entfernt.
Das würde obiges auch rechnen, und ist unübertroffen simpel.

Summe.jpg
 

abgdf

Guru
Ok, dieses "summe" ist aber ein sehr exotischer Befehl (oder ein selbstgeschriebenes C-Programm?). Nicht mal die Google-Suche nach Teilen der man-page wie "Gut fuer Gimp-Stundenzettel" findet was.
Zum Addieren von Spalten in einer Datei gibt es awk, das ist primär dafür gemacht.
(Ich persönlich schreibe mir dafür schnell ein Skript in Perl oder Python, weil ich das besser kann.)
Wie ich schon dachte, ist das Prüfen auf Pipe dafür nicht erforderlich.
 
OP
OsunSeyi

OsunSeyi

Hacker
Wofür denn die Frage ;)

Code:
#!/bin/sh
## summe [-t] [-2] [-v]
##
##	addiert alle Zahlen aus dem Clipboard, der Standardeingabe (Pipe) oder aus "$*",
##	je nach Zweck. Gut fuer Gimp-Stundenzettel oder um Spalten zu rechnen.
##
#										01.09.2012
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
										     . inc
	  TMP0=$SRC/tmp/summe0.tmp
	  TMP1=$SRC/tmp/summe1.tmp

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##	[-v]     zeigt die Rechnung (verbal).
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	VERBAL=`echo $* | grep  '\-v'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##	[-t]     hilft, Zeiten im Stundenzettel zusammenzurechnen.
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	 TIMES=`echo $* | grep  '\-t'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##	[-2]     gibt die zu rechnende Spalte an (Trenner ist Tab).
##		 das geht via Pipe oder aus der fluechtigen Zwischenablage.
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	COLUMN=`echo $* | sed 's|-v||g' | egrep  '^ *-[[:digit:]]+ *$' | sed 's|^.*-\([[:digit:]]\+\).*$|\1|g'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##	[1 2 -3] wird einfach addiert.
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	VALUES=`echo $* | sed 's|-[A-Za-z]\+||g'`

##	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##	ohne Option ("verbal" ausgenommen) wird aus der fluechtigen Zwischenablage
##	gelesen, Text wird vorher entfernt.
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	if [ -z "$VALUES" -a -z "$TIMES" -a -z "$COLUMN" ] ; then VALUES=`xsel -p` ; fi

#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#/////  S P A L T E N   A D D I E R E N  /////////////////////////////////////////////////
#=========================================================================================

  if [ -n "$COLUMN" ] ; then

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Teste auf Werteübergabe per Pipe.
#	Das geht nach langem Suchen auf diese Weise, siehe:
#	http://forum.linux-club.de/viewtopic.php?f=91&t=120294
#	Alternative zum read: tty bzw. tty -s und dann den Return-Code checken
#	read -t 0.1 TEST (geht nicht, wenn die Datei mit einer Leerzeile beginnt)
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	TEST=`tty | grep 'not a tty'`

	if [ -n "$TEST" ] ; then

#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#		Wurde etwas per Pipe übergeben:
#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		VAL=`	awk 'BEGIN { FS = "\t" }
				   { print $'$COLUMN'  }'				|\
											 \
			egrep '^ *-?[[:digit:]]+(\.[[:digit:]]{2})?$'`

		NUM=`	echo $VAL | sed 's| \+|+|g' | sed 's|+-|-|g'`
	else
#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#		Wurde nicht etwas per Pipe übergeben, probiere die Zwischenablage:
#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		VAL=`	xsel -p								|\
											 \
			awk 'BEGIN { FS = "\t" }
				   { print $'$COLUMN'  }'				|\
											 \
			egrep '^ *-?[[:digit:]]+(\.[[:digit:]]{2})?$'`

		NUM=`	echo $VAL | sed 's| \+|+|g' | sed 's|+-|-|g'`
	fi
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Rechnung und Ergebnis ausgeben:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	ERG=`echo 'scale=2; '$NUM | bc`

	if [ -n "$VERBAL" ] ; then echo -n ' '$NUM' =' ; fi

	echo -e $hellrot $ERG $def 
	echo    $ERG | xsel -b -i

	exit 0
  fi
#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#/////  S T U N D E N Z E T T E L :   Z E I T E N   A D D I E R E N  /////////////////////
#=========================================================================================

  if [ -n "$TIMES" ] ; then

	xsel -p    > $TMP0
	echo -n '' > $TMP1

	line=0						# aktuelle Zeile
	lines=`wc -l $TMP0 | sed 's| .*$||g'`		# Anzahl der Zeilen

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Damit auch Leerzeilen berücksichtigt werden, jede Zeile einzeln:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	while [ $line -le $lines ] ; do

		line=`expr $line + 1`			# hochzählen
		 row=`sed -n $line'p' $TMP0`		# Zeile auslesen

#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#		Zeilen mit Zeitangaben
#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		if [ -n "$row" ] ; then

#			~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#			Eine Zeitangabe ist z.B. "7.45 10.30":
#
#			Ersetze viertel, halbe, dreiviertel Stunden nach dezimal
#			Vertausche die beiden Zeiten (um abziehen zu können),
#			und füge ein '-' ein.
#
#			"$NUM" ist der String, mit dem 'bc' rechnen wird.
#			~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

			NUM=`echo $row | sed 's|\.15|.25|g' | sed 's|\.30|.5|g' | sed 's|\.45|.75|g'	|\
													\
			     sed 's|^\([^ ]\+\) \(.*\)$|\2-\1|g'`

#			Ergebnis rechnen, formatieren und ausgeben:

			echo 'scale=2; '$NUM | bc 							|\
													 \
			sed 's|0\+$||g' | sed 's|^\.|0.|g' | sed 's|\.$||g' | tr '.' ','		 \
													 \
			>> $TMP1

#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#		Leerzeilen
#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		else
			echo $row >> $TMP1
		fi
	done

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Das Ergebnis kommt in die echte Zwischenablage ("clipboard")
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

			cat $TMP1 | xsel -b -i
			echo 'Ergebnis ist im Clipboard'
	exit 0
  fi

#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#/////  Z A H L E N   A D D I E R E N  ///////////////////////////////////////////////////
#=========================================================================================

  if [ -n "$VALUES" ] ; then

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Anspruch ist, das ganze Blöcke incl. Labels und Daten (11.11.11) gerechnet werden.
#	Folgende Ersetzungen werden vorgenommen:
#
#			Zeilenumbrüche entfernen
#			alles, was mehrere Punkte hat (z.B. Daten), entfernen
#			Komma zu Punkt
#			alles, was keine Ziffer und kein und kein Minus Punkt ist, zu Leerzeichen
#			String trimmen
#			Leerzeichen zwischen den Zahlen zu je einem "+"
#			"+" und "-" = "-" für negative Zahlen, weil Minuszeichen auch an
#			anderer Stelle (in Texten) vorkommen können, mehrfache entfernen
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	NUM=`echo $VALUES 							|\
										 \
			tr '\n' ' '						|\
			sed 's|[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+||g'  |\
			tr ',' '.'						|\
			sed 's|[^-.[:digit:]]| |g'				|\
			sed 's|^[[:space:]]*||g'				|\
			sed 's|[[:space:]]*$||g'				|\
			sed 's|[[:space:]]\+|+|g'				|\
			sed 's|+-|-|g' | sed 's|--\+|-|g'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Rechnung und Ergebnis ausgeben:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	ERG=`echo 'scale=2; '$NUM | bc`

	if [ -n "$VERBAL" ] ; then echo -n ' '$NUM' =' ; fi

	echo -e $hellrot $ERG $def 
	echo    $ERG | xsel -b -i

	exit 0
  fi

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FIN@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Wie ich schon dachte, ist das Prüfen auf Pipe dafür nicht erforderlich.
Nein, natürlich nicht.
So gesehen.
Aber einfacher, wenn das Skript selber entscheidet und ich keine Option extra bemühen muss.
Ist doch nur für meinen Eigenbedarf.
Ausser dem ist das Thema als solches doch eine Frage wert??
 
OP
OsunSeyi

OsunSeyi

Hacker
Übrigens ist es doch bei vielen Programmen absolut normal:
Wie etwa "grep file" oder "cat file | grep".
 

abgdf

Guru
OsunSeyi schrieb:
Übrigens ist es doch bei vielen Programmen absolut normal:
Wie etwa "grep file" oder "cat file | grep".
Ich hab' jetzt nicht den Source-Code von grep angesehen, aber ich vermute, daß grep seine Optionen durchgeht, und wenn die Syntax des Aufrufs darauf hindeutet, daß kein Dateiname mitgegeben wurde, davon ausgeht, daß es von STDIN lesen soll. Ich glaube nicht, daß es den Unterschied ernsthaft prüft.

Im übrigen ist Deine zweite Variante ein "Useless use of cat".
So, jetzt bist Du wahrscheinlich sauer, aber ich mein's nicht böse. :D
 
Oben