Meine persönlichen Gedächtnisstützen der wichtigsten Werkzeuge ...
shopt -s extglob
shopt -u extglob
shopt -s globstar
ls **/*.jpg # Suche (auch) in Unterverzeichnissen
shopt -s dotglob
ls * # Anzeige (auch) versteckter Dateien (sonst ls .* noetig)
shopt -s nocaseglob
Reihenfolge
===========
tilde-expansion
variable-substitution
command-substitution
arithmetic expression
word splitting of expanded text
wildcard expansion
command-lookup
( expression ) # returns the value of expression (cf. files=(*) )
# This does NOT work in the general case
$ files=$(ls ~/*.jpg); cp $files /backups/ <= Whitespace in Dateinamen moeglich
#
# This DOES work in the general case
$ files=(~/*.jpg); cp "${files[@]}" /backups/ <= 1.) globbing und 2.) escaped Array bewahren White-Spaces in Dateinamen
$ files=$(ls) # BAD, BAD, BAD! <= Whitespace in Dateinamen
$ files=($(ls)) # STILL BAD!
$ files=(*) # Good! <= Globbing bewahrt White-Space
eval ...
printf "%10.10s\n" "$a" $b $c # Quoting !
printf "%b\n" "Hello\nWorld" # %b == %s mit Escape-Sequenzen
printf "%d\n" 011 0xff # oktal und hexadezimal
printf "%04d" 3 # 0-Padding => 0003
printf "%-15s:\n" Hugo # flush left
printf "%Farbe: #%02x%02x%02x;\n" 66 43 171 # hexdezimal mit 0-Padding (%X ist Klein, %X Gross-Darstlelung)
printf "%10.2 f\n" # Laenge 10 inkl. Dezimaltrenner und 2 Nachkommastellen (!)
printf "%-10.5s:\n" Willibald # 5 Zeichen mit Feldbreite 10 linksbuendig ausgeben => Willi :
printf -v var "%04d" 5 # 0005 => var
printf "%.5d\n" 5 => 00005
printf "%.4s\n" "string" => stri
printf "%${width}.${prec}f\n 14.7358
printf "|%*.*s|\n" 3 3 willi # => |wil|
printf "%x %X" 15 15 # f F
=========================================
Dezimale, oktale und hexadezimale Ausgabe
=========================================
Hex => Oct
printf "%o\n" 0x3a # => :
Oct => Hex
printf "%x\n" \072 # => 3a Octalwert MUSS 3-stellig sein
Oct => Dec
printf "%d\n" \072 # => 58
Oct => Char
echo $'\72' # => : Octalwert darf 1- bis 3-stellig sein (octal 72 == dezimal: 58)
echo $'\072' # => :
Hex => Char
echo $'\x3a' # => : (hexadezimal x3a == dezimal: 58)
Octal
printf "\033" # => ESC
Screen als Canvas
=========================================
printf "\033[%d;%dH" 10 10 # => Cursor an Position 10/10
echo "Hello"
alternativ
cursMov=$'\e[%d;%dH' # \e == \033
printf "$cursMov" 10 10
echo "Hello"
--------------------------------------------------------------------------
#!/bin/bash
# Variante 1: Escape-Sequences
: <<EOF
cu_row_col=$'\e[%d;%dH'
cu_row_col=$'\033[%d;%dH'
printf "$cu_row_col" ${2:-0} ${3:-0}
# printf "\033[%d;%dH" 5 10
echo "${1?}"
EOF
# Alternative: tput
# tput setab 1
# tput setaf 2
tput cup ${2:-0} ${3:-0}
echo "${1?}"
--------------------------------------------------------------------------
Precision (Bedeutung)
=====================
printf "%.5d\n" 12345 => 123456 # keine Bedeutung, falls Zahl mehr Stellen als precision
printf "%.5d\n" 5 => 00005 # falls Zahl weniger Stellen als precision: Ausgabe von precision Stellen mit 0-padding
%s # Maximalzahl an Zeichen
%-5.4s # 5 Stellen Feldbreite, maximal 4 Zeichen linksbuendig ausgeben
%.4s # maximal 4 Zeichen ausgeben
%f # Zahl Dezimalstellen
Flags
=====
Space-Flag
printf "% d\n" 15 -15 # Positive Zahlen mit ' ', negative mit '-'
0-Flag
printf "%05d\n" 15 # 0-Padding => 00015
#-Flag # Kennzeichnung von Oktal- und Hexadezimalzahlen
printf "%x %#x" 15 15 # => f 0xf
echo -n (kein Zeilenumbruch)
echo -e "Hello\nWorld\n" # Interpretation von Escape-Sequenzen
> file # file leer anlegen/ueberschreiben
printf "%s Hugo\n" > file 2>&1
printf "%s Hugo\n" &> file # 1 und 2 umleiten (dito >&)
#-------------------------
exec 0<file # dauerhafte Umleitung
exec 1>file # dauerhafte Umleitung
exec 5>&2 # Fehlerlausgabe (2) auf Ausgabe 5 "sichern" (=> 5 zeigt auf aktuelle Fehlerausgabe)
exec 2> /tmp/hugo # Fehlerausgabe aendern
exec 2>&5 # Fehlerausgabe "zuruecksichern" (2 zeigt auf aktuelles 5 == frueheres 2)
exec 5>&- # Sicherung loeschen (implizit 5 von 2 loesen)
#-------------------------
read a b c d # $d beinhaltet Rest der commandline
date=$(date) # == date=`date`
[ ] # == test (builtin command (strings, integers und Dateiattribute), word splitting und file name expansion)
[ "$var" -eq 0 ]
[ "$str" != "string" ]
[ -z "$str" ]
[[ ]] # test inkl. regular expressions (not builtin command => parameter expansion ohne word spliting und file name expansion)
file="file name" # now word splitting
[[ -f $file ]] && echo "..."
[[ -f $file1 && ( -d $dir1 || -d $dir2 ) ]] # Escape fuer Klammern nicht noetig
[ -f "$file1" -a \( -d "$dir1" -o -d "$dir2" \) ]
[[ "$hugo" = "string" ]] # Reiner String-Vergleich (da quoted right arguement)
[[ "$hugo" = pattern ]] # Cave: unquoted right argument => behandelt pattern analog "shopt -s extglob" wie auch case-statement, d.h.
[[ "$string" == hugo@(willi|frank)th?o ]] # das pattern muss den Vergleichs-String VOLLSTAENDIG abdecken
[[ "$hugo" =~ h[ae]inz ]] # extended regular expression (Muster muss string NICHT vollstaendig abdecken) gemaess "man regex 3"
[[ "$hugo" =~ "h[ae]inz" ]] # Cave: Muster ist reiner String 'h[ae]einz' (keine extended regular expression), muss Vergleichs-String jedoch NICHT vollstaendig abdecken
!= ist Negation zu =, ==
shopt -s extglob
[[ "$hugo" != +([0-9]) ]] # Keine Zahlen
while read line; do # cf. voriges Beispiel
[[ "$line" =~ H[a-z]inz ]] && printf "Muster gefunden: %s\n" "$line"
[[ "$line" =~ "H[a-z]inz" ]] && printf "String gefunden: %s\n" "$line"
done < <(echo -e "1. Heinz\n2. H[a-z]inz und Willi")
shopt -s extglob
echo ${*%%*(.gif|.jpg|.png)}
shopt -s extglob
array=($*) # Cave: Trennung bei Whitespace innerhalb von Elementen aus $*
echo ${array[*]%%*(.gif|.jpg|.png)}
#---------------------------------------------------------------------------------------------------------------------
shopt -s extglob
pattern=0.00000 # 5 Nachkommastellen
case $pattern in
*0[.]00000*([^0])) echo "Fein" ;; # Test auf nicht mehr als 5 Nachkommanullen
*) echo "Unfein" ;;
esac
#---------------------------------------------------------------------------------------------------------------------
datum=01.01.2022
datum=2022.01.01
datum=01.01.22
datum=22.01.01
if [[ "$datum" =~ ^[0-9]{2,4}[^0-9][0-9]{2}[^0-9][0-9]{2,4}$ ]]; then
printf "Fein\n"
else
printf "Unfein\n"
fi
#----------------------------------------
# In while-condition mit mehreren
# Bedingungen
# falls auf einer Zeile => durch ';'
# zu trennen
# ist nur deren letzte
# als Schleifenbedingung massgeblich
# while <list>; do
# <list>
# done
#
# Eine Zuweisung vor der Schleifen-
# bedingung auf derselben Zeile
# muss NICHT durch ';' # getrennt werden
#----------------------------------------
declare -i i=0 max=10
while (( i++ )); [ "$i" -lt "$max" ]; do # Nur letzte Anweisung ist Schleifenbedingung
echo "i: $i ($max)"
done
#---------------------------------------- # read in eine Variable trimmt leading und trailing whitespace
while read var; do
printf "%s\n" $var
done < <(cat << EOF
Hugo Willi Franz
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # <= Whitespace
EOF
)
=>
Hugo Willi Franz
^^^^^^^^^^^^^^^^^^^^ # kein Whitespace
#----------------------------------------
tr -s ' ' ' ' < file # '-s' ersetzt eine "sequence" des Folgezeichens in Eingabe => Kompression von Blanks
#----------------------------------------
((...)) oder $((...)) # $((...)) Posix ... ((...)) nicht Posix
if ((flag)); then ...; fi # Integer als true/false
(( var )) && ... # Test auf non-zero
test $(( a - 2 )) -ne 0 # Arithmetik: Variablen muessen nicht dereferenziert werden
((abs = (a >= 0) ? a : -a)) # Ternary verfuegbar
let a='(5+2)*3' # bei 'let' Klammern quoten
for ((i=1; i<=$1; i++)); do echo $i; done
if (( total > max )); then # da kein builtin sondern shell-syntax, werden '<>' nicht als redirection interpretiert
Listen: # Exit-code = Exit-code des letzten statements
<command>;<command>;...
<command> && <command> ...
grep -q goodword "$file" && ! grep -q badword "$file" && rm "$file"
grep -q goodword "$file" && ! grep -q badword "$file" && { rm "$file" || echo "Couldn't delete: $file" >&2; } # Cave: Semikolon vor schliessender Klammer
<command> <newline>
<command>
case-statement # Pattern analog pathname-expansion mit wildcards, character lists und ranges
case $1 in # Substring-Test (schnell)
*"$2"*) true ;;
*) false ;;
esac
case $1 in # Integer-Test
*[!0-9]*) false ;;
*) true ;;
esac
break 2 # zweite Schleife von innen verlassen
printf "%s" "$@" # Einzel-Quoting aller Parameter
printf "%s" $@ # Word-Splitting
printf "%s" "$*" # Gesamt-Quoting des Parameter-String
{01..10..2}
{a..z..2}
a*b?[[:lower:]][h-o] # Pathname-Expansion (unquoted ?*[] treated as file globbing parameters)
[[:upper:]][[:lower:]] # Gross-, gefolgt von Kleinbuchstabe
#-------------------
while read file; do
...
done < <(ls *.jpg) # Process substitution
#-------------------
while getopts "hx:" opt;do
case $opt in
h) puts "help" ; exit;;
x) var="$OPTARG" ;;
esac
done
#-------------------
Subshell () # erzeugt neuen Prozess
$(...) # command substitution
| ... # pipelines
( <command> ) # Befehle in '()'
prog() (....) # Funktion in Subshell
tar -cf - . | (cd /newdir; tar -xpf -) # tar aktuellen Verzeichnisses => stdout | subshell: cd und tar-Extraktion von stdin
# Cave: Da Subshell kein Verzeichniswechsel für Haupt-Shell !
Code-Block {} # kein neuer Prozess <=> Subshell
cd dir || {
...
}
Command-Group
{ ls ...; cd ...; cat ...; } >out 2>&1 # Cave: ';' auch nach letztem (!) Kommando, sonst wird '}' als Argument desselben interpretiert
[[ -f $CONFIGFILE ]] || { echo "Config file $CONFIGFILE not found" >&2; exit 1; } # Cave: 'exit 1' wuerde in Subshell nicht die aufrufende Shell beenden
{
read firstLine
read secondLine
while read otherLine; do
something
done
} < file
Parameter Expansion
===================
${var:-alternative} # falls var nicht gesetzt oder leer => alternative
${var-alternative} # falls var nicht gesetzt => alternative
${var:=default} # ggf. Zuweisung
${var:+default} # falls var gesetzt und nicht leer => default
for token in a b c; do
var="${var:+"$var "}$token"
done
${var:?Variable ist leer} # Fehlermeldung
${#var} # Laenge der Variablen
${var%.*} # Endung beschneiden
${file##*/} # Pfad abschneiden
printf "%s\n" ${passwd//?/*} # Passwort verschleiern
file=${file//+( )/_} # shopt -s extglob: Alle Blankfolgen durch '_' ersetzen
printf "%s\n" ${passwd/[[:upper:]]/*} # Ersetzung des ersten Grossbuchstabens
${var:2:2} # offset und length
Pruefung von Variablen
=========================================
Falls in "prog":
var={1:?}
dann
./prog "" # 1: Parameter ist Null oder nicht gesetzt
./prog # 1: Parameter ist Null oder nicht gesetzt
Falls in "prog":
var={1?}
dann
./prog "" # <alles ok>
./prog # 1: Der Parameter ist nicht gesetzt
#--------------------------------- # dito fuer Arrays (offset bezeichnet Element mit diesem Offset, length die Anzahl Elemente ab diesem)
array = (one two three four)
${array[@]:1} # two
${array[@]:1:2} # two three
#---------------------------------
${!var} # Dereferenzierung
${var^^}
${var^[h-k]} # Erstes Zeichen gross schreiben, sofern im Bereich h-k
${var,,[A-F]} # Alle Zeichen klein schreiben, sofern im Bereich A-F
$# # number of positional parameters
#---------------------------------
array=( fifi lala huhu )
printf "%s\n" "${array[@]/%fi/bu}" # Ersetzt in allen Elementen eine Nachsilbe fi => fibu lala huhu
printf "%s\n" "${array[@]//fi/}" # Loescht in allen Elementen jeweils alle Vorkommen von "fi" => lala huhu
printf "%s\n" "${array[@]/%[iau]/}" # Loescht in allen Elementen jeweils ein endstaendiges i,a oder u => fif lal huh
printf "%s\n" "${array[@]^^}" # Konvertiert alle Elemente zu Uppercase
#---------------------------------
declare -A arr
#---------------------------------
for i in "${!assoc[@]}" # ${!assoc[@]} <= Keys
do # ${assoc[@]} <= Values
echo "key : $i"
echo "value: ${assoc[$i]}"
done
#---------------------------------
while IFS=':' read file category; do # Assoziativer Array eines dynamischen Arrays
if [[ ! "${catA[*]}" =~ "$category" ]]; then # Array to String => Test auf Membership (String( nicht Pattern-)-Match auf Teilstring)
catA+=( "$category" )
fi
eval ${category}+=\( \$file \) # dynamischer Array (Name resultiert aus Variable)
fileA+=( $file )
done < "$config"
#- - - - - - - - - - - - - - - - -
for category in "${catA[@]}"; do
eval array=( \"\${${category}[@]}\" ) # String to Array
for file in "${array[@]}"; do
printf "%20.20s => %s\n" "$category" "$file"
done
done
#---------------------------------
arr=( a b c )
arr+=( d )
${arr[0]}
printf "%s\n" "${arr[*]}" # quoted "*" => ein String
printf "%s\n" "${arr[@]}" # quoted "@" => jeder Parameter wird ein String
printf "%s\n" ${arr[@]} # unquoted @ (oder *) => Word Splitting ueber alle Parameter
printf "%s\n" "${arr[@]:1:2}" # Zweites und drittes Array-Element jeweils ohne Word-Split ausgeben
printf "%s\n" "${arr[@]:1}" # Alle Array-Elemente ab dem zweiten ohne Word-Split ausgeben
printf "%s\n" "${#arr[*]}" # Laenge des Arrays (* oder @)
printf "%s\n" "${#arr[2]}" # Laenge des dritten Elementes
case var in
"" | *[!0-9.]* | *[!0-9]) ;; # Leer oder (Nicht Zahl oder Punkt) oder keine Zahl am Ende
esac # Cave: var muss vollstaendig durch Muster abgedeckt sein
set -- $2 $3 $1 # Resortierung '--' beendet Optionsliste fuer set
set -- $name $dial $address
set -a # '-'Kurzoption setzt eine Funktion (hier: Export aller folgenden Shell-Variablen)
set +a # '+' == unset einer Funktion
set -o allexport # Langform des Exports folgender Shell-Variablen mit Option -o
set +o allexport # '+' == unset
set -x # print commands after expansion before running them
set -v # print commands verbatim
set -o vi # vi-style behavior
result="$( ls )" # schlecht: Ausgabe durch command substitution variable zuweisen
usage(){
printf "%s\n" ${var:-Kein Wert}
} > ${1:-/dev/filedescriptor}
declare -n name=${var:-Leer} # Namensreferenz => name ist var
var+="a b c" # Konkatenierung (analog bei Array: arr=( a b ) arr+=( c d )
var=${var:0:$limit}
printf -v result "%c" "$var" # Zuweisung des ersten Zeichens aus var an Variable result
tmp=${var#?} # erstes Zeichen abschneiden =>
res=${var%"$tmp"} # alles bis auf das erste Zeichen abschneiden
echo var | tr 'a-z' 'A-Z'
case var in
y|Y) ... ;;
[aA] ... ;;
esac
substr=${string:0:$(( $end - 2))}
rightspaces=${var##*[! ]} # Alles bis auf letzten Whitespace rechts abschneiden
leftspaces=${var%%[! ]*} # Alles vom ersten Non-Whitespace bis zum Ende abschneiden
#-------------------------
while read; do # => $REPLY
...
done < file
#-------------------------
while read a b c; do # c erhaelt Rest jeder eingelesenen Zeile
...
done < file
#-------------------------
while IFS=";" read surname prename; do # Eine Zuweisung vor einem Befehl macht die Variable lokal bezueglich des Befehles
... # Cave: Zuweisung vor builtin bleibt auch nach Beendigung des builtin gueltig
done < file
#-------------------------
while read line; do # Erst nach Einlesen der Zeile IFS veraendern ...
IFS=\;
set -- $line
echo "$1 - $2 - $3"
IFS=$'{ \t\n}' # und restaurieren
done < Hugo
#-------------------------
cat a.txt | tr 'aeiou' 'AEIOU' > out.txt
#-------------------------
{ # Gruppierung (nicht Sub-Shell)
date
cat report.txt
} | mail -s "Hugo" name@adress
#-------------------------
IFS=. read -ra ip_elements <<< "127.0.0.1" # Here-String als Standardeingabe (Manual: "The word is expanded and supplied to the command on its standard input.")
#-------------------------
files=file1,file2,file3,file4
mapfile -t -d ',' filesArr <<< "$files" # Cave: Here-String => haengt am "Dateiende", damit an file4 ein Newline an =>
mapfile -t -d ',' filesArr < <(echo -n "$files") # besser: Ausgabe ohne Newline
#-------------------------
if grep -q "txt" <<< "$VAR" # Here-String wird zu Standardeingabe
then
echo "$VAR contains the substring sequence \"txt\""
fi
while read element ; do
echo "$element" 1>&2
done <<< $(echo ${ArrayVar[*]}) # Here-String
#-------------------------
{ # Gruppierung mit Umleitung der Standardausgabe
while IFS=":" read team lead rest; do # Cave: IFS gilt hier nur fuer read !
printf "%s\n" "$dashLine"
printf "%30.30s: %-40.40s %s\n\n" "$team" "" "$lead"
printf "%30.30s: %-40.40s %s\n\n" "Scope-ID" "Anteil" "Scope"
IFS=":"
read -a claimArr <<< "$rest" # Zerlegung von $rest als Here-String
for claim in "${claimArr[@]}"; do
scopeId=${claim%|*}
anteil=${claim#*|}
printf "%30.30s: %-40.40s %s\n" "$scopeId" "$anteil" "${scopeHash[$scopeId]}"
done
IFS=" "
done < $teamfile
} > $outfile
#-------------------------
cat "$@" | while IFS=";" read line; do
...
done # Mehrere Dateien einlesen
#-------------------------
while IFS=";" read line; do
...
done < <(cat "$@") # dito via process-substitution
#-------------------------
IFS=";" read a b c d < $file # Erste Zeile einlesen (Zuweisung vor command bewirkt Lokalitaet)
#-------------------------
{
read line1
read line2
} < $file
#-------------------------
for i in {1..4}; do
read lines[${#lines[@]}] # ziemlich abgehoben (Index ist immer die aktuelle Zahl von Elementen des Array)
done < $file
#-------------------------
mapfile -t -n 4 lines < $file # n 4 (4 Zeilen einlesen) t (trailing newline entfernen)
printf "%s\n" "${lines[@]}"
#-------------------------
read -a array -p "Bitte Werte eingeben"
printf "%s\n" "${array[@]}"
#-------------------------
for file in {a..z}$RANDOM; do # besser als touch ...
> $file
done
#-------------------------
cut -c 22-24 $file | head -n3
cut -d : -f 1,5 /etc/passwd
#-------------------------
names="Willi,Franz,Hugo"
IFS=","
arr=( $names )
printf "%s\n" ${arr[2]} # => Hugo
#-------------------------
set -- $var # Word-Split => $1,$2,$3, ...
#-------------------------
Regex # im unterschied zu file expansion
=====
. # jedes Zeichen
* # 0 oder beliebig viele des vorigen Zeichens
File expansion
==============
* # matched keine dot-files
.* # matched dot-files
#-------------------------
printf "%s\n" {1..10} |
awk '
{ total+=1 ; }
END { print total; }
'
#-------------------------
shopt -s extglob
?(heinz|franz) # ein oder kein
*(heinz|franz) # kein oder beliebige
+(heinz|franz) # ein oder beliebige
@(heinz|franz) # entweder oder
!([abc0-9]*) # weder noch (Cave: Muss im Gegensatz der vorigen (logischerweise) den gesamten Vergleichs-String abdecken !)
# Cave: '*' ist hier beliebige Zeichenfolge (globbing), nicht "0 oder mehrere" (regex)
---- Beispiel -----
shopt -s extglob
for string in "abc" "bbc" "cbc" "dbc"; do
case $string in
!([ab]*)) printf "%s did not match a or b at beginning\n" "$string" ;;
*) printf "%s did match a or b at beginning\n" "$string" ;;
esac
done
time <command> # Messung der Ausfuehrungszeit
#-------------------------
printf "%s\n" "hugo" "willi" | { # common subshell
<command>
<command>
}
read -r # backslash literally einlesen
#-------------------------
rest="hugo:willi:franz"
IFS=":"
read -a array <<< "$rest"
printf "Array-Element: %s\n" "${array[@]}"
#-------------------------
printf "%s " "a" "b" | {
read -a arr # Array einlesen
printf "%s\n" ${arr[1]}
}
#-------------------------
read -n 1 var # nur 1 Zeichen einlesen
read -s var # Ausgabe der Eingabe unterdruecken (Passworte)
read -p "Eingabe: " var # Eingabeaufforderung
read -p "Weiter ? (j/n): " -s -n 1 var
read -t 2 var # Timeout 2 Sekunden
#-------------------------
string="hugo:willi:franz"
read -a array -d ':' <<< "$string" # -d: read up to delimiter
printf "%s\n" "${array[@]}"
=> hugo
#-------------------------
select name in Hugo Franz Willi Exit; do
case $name in
Hugo) echo "..." ;;
Franz) ... ;;
Willi) ... ;;
Exit) exit 0 ;;
*) echo "Ungueltige Auswahl" ;;
esac
done
#-------------------------
set -x # Ausgabe der Verarbeitungsschritte
#-------------------------
eval "$(date "+year=%Y" month=%m day=%d")" # funktioniert, da in date-Formatstring jeder Zusatztext erlaubt ist
date '+%d.%m.%Y' --date=20081128 # => 28.11.2008
date '+%d.%m.%Y' --date=081128 # => 28.11.2008
date '+%d.%m.%Y' -d 081128 # => 28.11.2008
#-------------------------
{
echo "a"
echo "b"
} > file # gemeinsame Umleitung
#-------------------------
join file1 file2 # Spaltenweise Zusammenfassung anhand gemeinsamen "Primaerschlussels"
#-------------------------
format -s ... # split long lines
format -w 60 ... # wrap bei 60 Spalten
#-------------------------
Druck
lpr
lpstat
lpq
lprm
lpoptions
#-------------------------
export -p # Ausgabe der Umgebung
#-------------------------
if [ -n "$a" -o -n "$b" ] # -a und -o sind Test-Operatoren
if [-n "$a" ] || [ -n "$b" ] # || und && jedoch sind Shell-Operatoren
if [ "$a" = a ] || { [ "$b" = b ] && [ "$c" = c ];}; then ... grouping mit abschliessendem ';' <= ';' wird sonst als Argument interpretiert
#-------------------------
cat << "EOF" # quoted => keine Variablen-Substitution
$a # $a wird nicht substituiert
EOF
#-------------------------
# falls noexpandtab gesetzt ist
cat <<-ENDE
Hugo
Willi
ENDE
#-------------------------
for file in $(cd /dir; echo *.txt); do # command-substitution
diff /old/dir/$file $file
done | more
Fortgeschrittene Beispiele
==========================
${vec[@]^^[aeiou]}
${vec[@]//[aeiou]/A}
---------------------------------------------------------------------------------------
Match-Groups
------------
string=franz_hugo_willi
[[ $string =~ (fritz|h(ug|ag)o)_willi ]] # extended regular expression (man regex 3)
echo ${BASH_REMATCH[@]}
=> hugo_willi hugo ug
---------------------------------------------------------------------------------------
string=aabbbbycc
[[ $string =~ a{2}b{2,3}[xyz]c{1,2} ]]
for element in a b c d e; do
list=${list:+$list,}$element
done
names=([0]="Bob" [1]="Peter" [20]="$USER" [21]="Big Bad John") # sparse array
photos=(~/"My Photos"/*.jpg) # globbing => array
# nicht Aufloesung eines Ausdruckes: ( expression ) returns the value of expression
birke=baum
arr=(birke fichte tanne)
declare -A assoc=([heinz]=breinlinger [ingrid]=daubechies)
${arr[@]^[ft]}
${arr[@]/fich}
${arr[@]//e/E}
${!arr[0]^^}
${assoc[@]^[td]}
# falls noexpandtab gesetzt ist
shopt -s extglob
set -x
mapfile -t <<- ENDE
Hugo1 Hugo2
Willi1 Willi2
ENDE
printf "%s\n" "${MAPFILE[@]}" # zeilenweise Ausgabe, da quoted
printf "%s\n" ${MAPFILE[@]} # wortweise Ausgabe, da unquoted
IFS="|"
read -a array <<- ENDE
Hugo|Willi|Franz
ENDE
printf "%s\n" "${array[@]}" # geaenderter internal field separator
# Anstelle IFS zu aendern, explizit einen delimiter setzen
file
----
Hugo|Franz|Willi
Markus|Dieter|Franz
mapfile -d '|' -t < file
printf "%s\n" "${MAPFILE[@]}"
Hugo
Franz
Willi
....
------------------------------------------------------------------------------------------
cat <<EOF
$Hugo
EOF
------------------------------------------------------------------------------------------
cat <<'EOF' # keine Ersetzungen
$Hugo
EOF
------------------------------------------------------------------------------------------
cat <<-EOF
$Hugo # Tab-Unterdrueckung
EOF
------------------------------------------------------------------------------------------
myfunction <<EOF # Funktionsaufruf mit 2 Parametern
param1
param2
EOF
------------------------------------------------------------------------------------------
: <<'DISABLED' # Pogramm-Code auskommentieren
command
command
DISABLED
------------------------------------------------------------------------------------------
command <<< $var # Here-String => stdin fuer command
cat <<< $var
cat <<< 'Escaped variable $var' # keine Ersetzungen
------------------------------------------------------------------------------------------
# command expansion mit awk
------------------------------------------------------------------------------------------
colLen=$(awk -F ';' '
BEGIN{
for(i=1;i<=130;i++){
colLen[i]=0;
OFS=";";
rightMostCol=0;
}
}
{
#----------------------------------------------------------------------------
# Maximale Feldzahl aktualieren
#----------------------------------------------------------------------------
if(NF > rightMostCol){
rightMostCol=NF;
}
#----------------------------------------------------------------------------
# Spaltenbreiten bestimmen
#----------------------------------------------------------------------------
for(i=1;i<=NF;i++){
#--------------------------------------------------------------------------
len=length($i);
if(len > colLen[i]){
colLen[i]=len;
}
}
}
END{
for(i=1;i<=rightMostCol;i++){
printf(" %s",colLen[i]);
}
}
' dummy.csv)
printf "Laenge: %s\n" "$colLen"
#-------------------------------------------------------------------------------------
# URL-encoded String dekodieren
# Hexadezimal 21 ist '!'
# Leerzeichen koennen als '+' oder %20 codiert sein
#-------------------------------------------------------------------------------------
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
echo 'a%21b' | while read; do echo -e ${REPLY//%/\\x}; done # Alle mit % gekennzeichnenten Hexadezimalkodierungen durch Hex-Prefix kennzeichnen und damit implit dekodieren
while read; do
: "${REPLY//%/\\x}"
echo -e ${_//+/ } # Whitespace ist mit '+' URL-codiert
done
: is a BASH builtin command. Here it just takes in a single argument and does nothing with it.
The double quotes make everything inside one single parameter.
_ is a special parameter that is equal to the last argument of the previous command, after argument expansion. This is the value of REPLY with all instances of '%' replaced with '\x'.
${_//+/ } replaces all instances of '+' with ' '.
#-------------------------------------------------------------------------------------
cargo build > >(tee -a "$temp_file") 2> >(tee -a "$temp_file" >&2) Beispiel fuer process substitution bei Ausgabe
Zwischen Operator-Command und Move-Command ist Operator-Pending-Mode
=====================================
{command}{number} {text-object == movement-command}
{number}{command} {text-object == movement-command}
In ex-Mode wird Text mit Zeilenadressen bestimmt, in vi-Mode mit Text-Objekten/Movements
- Folding
Interaktiv
V (Visual) + <move>
zf
Ein Fold
zo (open)
zc (close)
zf (create)
zd (delete)
Mehrere Folds
zO (alle unterhalb Cursor oeffnen)
zC (alle unter Cursor schliessen)
zR (alle oeffnen)
zM (alle schliessen)
zD (alle unterhalb Cursor loeschen)
zE alle Folds loeschen
:1,5 fo(ld)
:set foldmedthod = marker,manual,indent,syntax, ...
:set foldmarker={{{{,}}}}
Ansicht mit (manuell angelegten) Folds speichern
:mkview
Ansicht mit Folds laden
:loadview
- Kleinbefehle
. letzten Befehl wiederholen
Ctrl-f,Ctrl-b,Ctrl-u,Ctrl-d (ganze, halbe Seite nach unten/oben)
Ctrl-y,Ctrl-e (1 Zeile weiter nach unten/oben)
{,} next, previous paragraph
z10l z10h Bildschirm 10 Zeichen nach links/rechts
zH halben Bildschirm nach rechts
z10h 10 Spalten nach rechts
zL halben Bildschirm nach links
z17l 17 Spalten nach links
Bildschirmspruenge
H (igh)
M (iddle)
L (ow)
z
z.
z-
a,i,A,I,o,O
10i-<ESC> (fuegt 10 '-' ein)
H,M,L Cursor nach oben, Mitte, unten
10H (10 Zeilen unterhalb Oberkante)
5L (5 Zeilen oberhalb Unterkante)
h,10j,5k,3l
80| => Springe zu Spalte 80
g0
Im folgenden sind '/' und '?' fuer Vorwaerts/Rueckwaerts austauschbar
---------------------------------------------------------------------
d/Hugo (Loesche bis Hugo)
c/Willi (Aendere bis Willi)
y/Franz (Kopiere bis Franz)
y?a (Kopiere rueckwaerts bis einschliesslich a)
d- (Loesche bis Anfang der vorherigen Zeile)
cG (Aendere bis Dateiende)
dH (Loesche bis Oberkante Bildschirm)
cn (Aendere bis zum naechten gefundenen Muster)
"2p (2. Loeschung (in Buffer 2) rueckgaengig machen)
"_daw Aktuelles Wort in "blackhole" register speichern (== Loeschen ohne undo/redo)
'_' ist blackhole-register
"a7yy (7 Zeilen in Buffer a)
"aP (vor Cursor Buffer a einfuegen)
"Ay) (Bis Satzende an Buffer a anhaengen)
G (Dateiende)
4G (Gehe zu Zeile 4)
% (Sprung zu korrespondierendem Klammerpaar)
0,$ (zu Zeilenanfang/-ende)
_ oder ^ (zu erstem Zeichen der Zeile)
3yb oder y3b (3 Worte zurueck kopieren)
5yl oder y5l (5 Zeichen zurueck kopieren)
Ctrl-g (Dateistatus)
"ayw
"ap
r,R
10r- (ersetzt 10 Zeichen durch '-')
Vr- (ersetzt in visuell markierter Zeile alle Zeichen durch '-')
yl Kopiere aktuelles Zeichen
y$ alles bis Zeilenende kopieren
y0 dito bis Zeilenanfang und vor aktuellem Zeichen
s (== cl)
Ersetzt EIN Zeichen mit beliebig viel Text
7s (ersetzt 7 Zeichen und entspricht daher praktisch R)
d2w,d3h
db
d/letztes_Wort (move ist ein Pattern)
g modifiziert Folgebefehl
-------------------------
g-Ctrl-a
Ctrl-a inkrementiert die erste Zahl einer Zeile
Dies gilt auch in einem Mit Shift-v gewaehlten Bereich
mit Modifier 'g' davor werden alle ersten Zahlen des Bereiches zum jeweils
vorherigen, um 1 inkrementierten Wert !
1 => 2
1 => 3
1 => 4
1 => 5
1 => 6
gj,gk,g0,g$ (Navigation nicht nach Editor-, sondern Bildschirmzeilen)
gUiW (Uppercase inside Word (non-whitespace))
gUE (Grosschreibung bis Wortende (non-whitespace))
gue (Kleinschreibung bis Wortende)
gUge (Grosschreibung zurueck bis Ende des letzten Wortes)
guG (lowercase bis zum Ende des Dokumentes)
gUG (uppercase ...)
- undo
Chunks werden mit jedem Wechsel von Normal- zu Insert-Mode festgelegt
(zusaetzlich auch durch Pfeiltasten bei Navigation)
u (undo)
U (Undo gesamte Zeile, solange Cursor auf Zeile bleibt)
Ctrl-r (redo)
g~ Case-Wechsel
gR (virtual replace mode => Tab als Folge von Blanks interpretieren)
~ Case-Wechsel
30~ Case-Wechsel der naechsten 30 Zeichen
> oder < oder =
Ctrl-o und Ctrl-i (zwischen letzten Sprungmarken vor- und zuruecknavigieren)
S. 138 "Practical Vim"
:set suffixesadd+=.rb (.rb in Liste automatischer Suffix-Ergaenzungen aufnehmen)
falls Cursor auf Dateiname steht, z.B. file
gf => Oeffne file.rb (Mnemo: goto file, real g (== modify Folge-)Befehl f (== find) zu Datei anstelle Zeichen in Zeile)
Ctrl-o => Ruecksprung zu voriger Datei (aus welcher Absprung erfolgte)
"ac2w (naechste 2 Worte aendern und Original in Register a)
Visual Mode
zeichenweise
v
viw (visual inside word)
vaW (visual around non-whitespace)
zeilenweise
V
spaltenweise
Ctrl-v
Aenderungen fuer weitere Zeilen werden nach <Esc> uebernommen
o (springt an anderes Markierungs-Ende)
Ctrl-g (toggled zwischen Visual- und Select-Mode (direktes Ueberschreiben analog Windows))
gv (modified v): markiert zuletzt markierten Bereich erneut
Vr- (ersetzt jedes Zeichen der Auswahl mit '-')
Insert-Mode
Ctrl-d (Auszug)
Ctrl-t (Einzug)
Ctrl-h (Zeichen loeschen)
Ctrl-w (Wort zurueck loeschen)
Ctrl-u (Bis Zeilenanfang loeschen)
Ctrl-o (Wechsel zu Insert-Normal-Mode: Ein Schuss in Normal-Mode)
Ctrl-r 0 Register 0 ausgeben
Ctrl-r / letztes Suchfeld ausgeben
Ctrl-r Ctrl-p 0 (dito, jedoch ohne Einrueckungen)
Ctrl-r " unnamed register ausgeben
Ctrl-r = 20 * 5 (Rechenergebnis einfuegen == numerisches Register ausgeben)
Ctrl-v (Zeichen woertlich eingeben)
Ctrl-v 065 (ga zeigt Codierung des aktuellen Zeichens an)
Ctrl-v <Tab> (Tabulator ohne Expansion eingeben)
Ctrl-v u{1234}
Ctrl-k Digraph-Code (:digraph)
Markieren
ma
'a
`a
`` Rueckkehr zu vorigem Absprungpunkt (Auto-Sprungmarke)
'' Rueckkehr zu voriger Absprungzeile (Auto-Sprungmarke)
mA Grossbuchstaben => Datei-uebergreifend == global mark
- Doppelbefehle sind Shortcuts und beziehen sich auf die aktuelle Zeile
cc
>>
dd
yy
gUgU (oder gUU)
xp (Tausch zweier Zeichen => "transpose" als Merkhilfe)
- Großbefehle sind ebenfalls Shortcuts und beziehen sich auf den Rest der Zeile oder die ganze Zeile
C (Rest der Zeile) == c$
D (Rest der Zeile) == d$
2D 2 Zeilen loeschen
Y (bezieht sich auf ganze Zeile)
10Y 10 Zeilen kopieren
S (bezieht sich auf ganze Zeile)
10S (substituiert 10 Zeilen)
4J (4 Zeilen verbinden)
- Text-Objekte (i hier analog a: a(round) oder i(inside) )
aW
ap
a) == ab
a} == aB
a]
a>
a'
a"
at (Tag)
- Suchen/Finden
:s/Hugo/Willi/gc
=> falls nun Ersetzung fuer ALLE Zeilen gewuenscht
:%s//~/& Ersetzung des letzten Suchmusters duch letztes Ersetzungsmuster mit denselben Flags wie zuvor
g& Kurzform des vorigen ("global alles gleich" oder "modifiziert dasselbe")
:s/Hugo/Willi
:& Wiederholung der letzten Substitution (fuer nun aktuelle Zeile), jedoch nicht den letzte Flags
g& Wiederholung der letzten Substitution fuer alle Zeilen
:&& Wiederholung der letzten Substitution mit den letzten Flags
:vimgrep /hugo/g *.rb Suche in allen *.rb-Dateien (und Editierung der Treffer)
:set (no)hlsearch Highlighting fuer Suchergebnisse an/aus
:set (no)hls
/,?
/Hugo/e Cursor auf Ende des Treffers positionieren
n,N
gn,gN visual mode fuer naechsten Treffer
:%s/Burg/Berge/g
/~ (Tilde ist letzter Ersetzungsusdruck) => Suche nach Berge
:cnext naechster und
:cprev vorheriger Treffer
f,F,t,T
10,20g/Hugo/s/Franz/Willi/g
*,# (Wort unter Cursor vorwaerts oder rueckwaerts)
:set ignorecase
:set smartcase
/foo\C case-sensitive search
/Foo\c case-insensitive search
:s/Willi/Hugo/c (confirm)
y,n,q(uit),l(ast),a(ll)
Ctrl-e Bildschirm nach oben
Ctrl-y Bildschirm nach unten
Posix-Character-Classes
[:alnum:],[:alpha:],[:blank:] (space und tab),[:digit:],[:space:] (Whitespace),[:lower:],[:upper:]
- Sessions
:mksession ~/Downloads/Sitzung.txt
vim -S ~/Downloads/Sitzung.txt
- Macro
qa (in Register a speichern)
qA (an Makro in Register a anhaengen)
q (Aufzeichnung beenden)
=> qaq (Register a loeschen)
@a
4@a (Makro aus a 4 mal anwenden)
@@ (letztes Makro anwenden)
Ctrl-V <move>:normal @a (aus Visual-Mode in ex-mode und fuer markierten Bereich Makro aus a ausfuehren)
auf diese Weise kann alternativ zu Ctrl-v spaltenweise editiert werden, indem die Editierung des
Feldes in Spalte 1 aufgezeichnet und danach fuer weitere Zeilen wiederholt wird.
- Command-Line-History
q:
- Search-History
q/
- Filterung in vi-Mode
====================
Cave:
2 Formen
!<number><movement><command>
<number>!<movement><command>
Movement-Command nach '!' muss mehrere Zeilen umfassen und bezieht sich auf alle Zeilen von Anfang bis Ende der jeweiligen Zeile
also nur moeglich: (),G,{},[],+,-
Beispiel
!10+ (naechste 10 Zeilen)
10!+ (naechste 10 Zeilen)
!! ist Abkuerzung fuer aktuelle Zeile
!) <command> (bis ans naechste Satzende durch <command> filtern)
- Command-Line
:edit! Datei neu editieren, alle Aenderungen implizit verwerfen,
:set (no)wrap(margin)
:set (no)number
:set (no)hls Toggle Syntax-Highlighting-Suche
:syntax on|off (Syntax-Highlighting)
:shell
Ctrl-f (Command-Line Window == History)
Ctrl-z (Stop und Shell aufrufen => Beenden/Rueckkehr mit fg)
dito
:stop => wie Ctrl-Z
:!ls
:r!ls (Ausgabe von ls unterhalb Cursor einlesen)
:7r!ls (dito unterhalb Zeile 7)
:$!uptime (letzte Zeile durch Laufzeit ersetzen)
:10,20! sort -t',' -k2
:source hugo.vim (wenn hugo.vim ex-Befehle enthaelt)
:buffers
:jumps (=> Jump-List)
:changes (=> Change-List)
:w >> bestehende_Datei
:w %.new (Speichern in <aktuelle Datei>.new)
Auch Datei-uebergreifend kopieren
:10,20yank a
<Datei-Wechsel>
"ap
:bnext,bprevious,bfirst,blast,bdelete (Nummer oder Name)
:3,5 bdelete
:buffer 2 Wechsel zu Buffer 1 (== zweiter editierter Datei)
:b1
:b2
:n(ext) (naechste Datei editieren)
:1,10# (Zeilennummer temporaer einblenden)
:put (paste immer UNTER die aktuelle Zeile im Unterschied zu p !)
:args
:args *.rb (befuellt die Argument-Liste <=> Buffer-Liste jedoch davon unbeeinflusst) => nun moeglich
:next
:prev
:first
:last
:argdo
:qa(ll)!
:wa(ll)!
:argdo normal @a
fuer alle Elemente der Argument-Liste Makro a ausfuehren
:argdo write (== :wa)
:e(dit)! Datei neu einlesen (== Aenderungen verwerfen)
:e Hugo.txt (weitere Datei editieren)
% ist aktuelle Datei
# ist alternative Datei
:buffer# (Wechsel zur jeweils anderen Datei)
:r# Zweite Datei in erste einlesen
Autocompletion
==============
Ctrl-n Autocompletion aus generic wordlist
CTRL-x (gefolgt von CTRL-...) cf. Pocket Reference Seite 47
Auswahl mit CTRL-n/-p/-y
Abbuch mit CTRL-e (end)
... CTRL-n/-p Suche in mit 'complete' festgelegten Quellen
complete-List: .,w,b,u,t,i
d.h. effektiv in vorherigen oder folgenden Zeilen des aktuellen Buffers "."
... CTRL-f Autocompletion von Dateien mit Auswahl (in Insert-Mode)
... CTRL-d Macros
... CTRL-k Dictionary (nach via 'dictionary' festgelegter Liste)
In .vimrc:
set complete+=k
Autovervollstaendigung auch innerhalb von dictionaries (zusaetzlich zu ".,w,b,u,t,i")
set dictionary+=~/.vim/teams.dict
... CTRL-l Zeile in vorherigem Text derselben Datei
... CTRL-s Spelling, sofern 'spell' gesetzt ist
... CTRL-t Thesaurus via 'thesaurus'
Hugo Ctrl-X <Tab>
Suche in Wortliste der aktuellen Datei nach Worten, welche mit Hugo beginnen fuer autocomplete
Ctrl-n (next)
Ctrl-p (previous)
Ctrl-y (yes)
Ctrl-e (end ohne Uebernahme)
Trick:
Ctrl-x Ctrl-k Aufruf der Autocomplete-Liste
Ctrl-p Sprung eine Zeile vor erstem Element == aktuell editierte Zeile
alternativ fuer Autocomplete-Liste des aktuellen Buffers anstelle des Dictionaries
Ctrl-x Ctrl-n Ctrl-p => Sprung ueber Liste (== editierte Zeile)
Ctrl-x Ctrl-p Ctrl-n => Sprung unter Liste (== editierte Zeile)
Hugo => Autofilerung der angezeigten Liste nach allen mit 'Hugo' beginnenden Eintraegen
=> Eingabe mit fortlaufend aktualisiertem Autocomplete
cf. S. 238 "Practical Vim"
Filename-completion
:pwd => aktuelles Verzeichnis
:cd /usr/local/bin
i my Ctrl-x Ctrl-f => Dateiliste aus /usr/local/bin zur Auswahl fuer alle mit 'my' beginnenden Dateien
:cd - => Rueckkehr zu urspruenglichem Verzeichnis (des aktuellen Buffers)
analog 'cd -' in Shell (=> vorheriges Verzeichnis)
:Explore,Vexplore,Sexplore,edit
:Explore ~/Downloads
:browse open
:col Ctrl-d (Liste der Moeglichkeiten mit col...)
:col <tab> (schrittweise durch Liste der Moeglichkeiten mit col...)
:colorscheme Ctrl-d (Anzeige der Farbschemata)
:Ctrl-r Ctrl-w (uebernimmt Wort unter Cursor auf Kommandozeile)
:ls
% ist aktueller Buffer
# ist alternativer Buffer
:tabnew,tabnext,tabprevious,tabmove N,tabclose,tabonly
gt,gT,1gt,tabs,tabm 0
:registers
:10 (gehe zu Zeile 10)
:10,20t.
:1,7y
:2,9p
:.,/while/d (von aktueller Zeile bis Zeile mit Muster 'while' loeschen)
:%y Alle Zeilen kopieren
:100;+5p (';' bewirkt relative Adressierung zu Anfangszeile, bzw. Anfangszeile wird zu aktueller Zeile => identisch zu 100,105p)
:3,8j
:10,20co17 == 10,20t17
:10,20m. (move statt copy)
:17,19d
:5,25 normal A; (am Zeilenende ';' anfuegen)
:%normal yi"$p (Kopiere in allen Zeilen innerhalb '"' und gib an Zeilenende aus)
:% normal i// (Allen Zeilen "//" vornstellen)
:5,25g/Hugo/normal @a (Macro aus Register a auf Zeilen in Range 5-25, welche Hugo beinhalten, anwenden)
:v/href/d (reziprokes global: Alle Zeilen loeschen, welche nicht href beinhalten )
:%s/Hugo/Willi/g
:/<Start>/+1,/<End>/-1d (Zeilen zwischen Mustern loeschen)
:'<,'> Range bei visueller Auswahl
:.,.+3p aktuelle und 3 Folge-Zeilen ausgeben
:'as/Hugo/Willi/g in Range mit Markierung 'a' substituieren
:5co0 (0 ist virtuelle Zeile oberhalb Datei => An Anfang kopieren)
:'<'>t0 (Range an Anfang kopieren)
:t. (Duplizierung)
:%s/\v ... (very magic == nur Buchstaben, Zahlen und '_' ohne Sonderbedeutung)
Beispiel
30.09.2021
:2,41s/\v([0-9]{2})\.([0-9]{2}).([0-9]{4})/\3-\2-\1/
=>
2021-09-30
Beispiel: Ersetzen eines 1000-Trennpunktes
:%s/\v([0-9]+)\.([0-9]{3})/\1\2/g
:10mark a
:10;+10w >> Hugo.txt (Zeilen 10-20 an Hugo.txt anhaengen)
:17r Hugo.txt (Hugo.txt nach Zeile 17 einlesen)
:/Markierung/r Hugo.txt (Hugo.txt nach Zeile mit Muster "Markierung" einlesen)
:%s/Hugo/"\1"/g
:%s/\v([a-z]+)/"\1"/g (Alle Worte in '"' setzen)
:%s/\V ... (very non-magic)
"uY Zeile in Register u speichern
/\VCtrl-ru non-magic-Suche nach Inhalt von Register u
:%s//Willi nutzt letzes Suchmuster fuer Ersetzung
:g/AMC/s/\(AMC:[^<]\+\)/<em class="demo">\1<\/em>/ <= Einfuegen eines Class-Tags
:%s//<Ctrl-r 0>/g letztes Suchmuster durch Inhalt des Registers 0 ueberall auf allen Zeilen ersetzen
:%s//\=@a/g dito, jedoch mit Macro aus Register a
:%s//~/g letztes Suchmuster durch letztes Ersetzungsmuster auf allen Zeilen ueberall ersetzen
:g//d Alle Zeilen mit letztem Suchmuster loeschen
:g/muster/w > Muster.txt Alle Zeilen mit Muster in Datei Muster.txt schreiben
:g/Hugo/s/\(Willi\|Franz\)/"\1"/g Auf allen Zeilen mit Hugo alle Vorkommen von Willi oder Franz in '"' setzen
:g/\vHugo/s/(Willi|Franz)/"\1"/g very-magic: Auf allen Zeilen mit Hugo alle Vorkommen von Willi oder Franz in '"' setzen
:g/\vHugo/s/(Willi|Fr%(a|e)nz)/"\1"/g very-magic: Auf allen Zeilen mit Hugo alle Vorkommen von Willi oder Franz oder Frenz in '"' setzen, dabei Klammer mit %(a|e) nicht zaehlen
:v//d invers zu vorigem => alle nicht dem vorigen Suchmuster entsprechenden Zeilen loeschen
:g!//d analog :v//d
:g/ToDo/yank A (Alle Zeilen mit ToDo in Register a verketten)
:g/ToDo/t$ (Alle Zeilen mit ToDo ans Dateiende kopieren)
:g/{/ .+1,/}/-1 sort (Cave: Blank nach erstem Suchmuster: Abschnitte zwischen '{}' sortieren)
Fuer jede Zeile mit "{": Sortiere von "aktueller Zeile + 1" bis eine Zeile vor "}"
:s/\v:[^:]+:/[&]/g (very-magic: Alle in ':' eingeschlossenen Worte in '[]' einschliessen)
:g/Syntax/.,/Syntax-Ende/-1 move /Parameters/-1
entspricht Muster :[range]g(lobal)/Pattern/ Command
Pattern: /Syntax/
Befehl: .,/Syntax-Ende/-1 move /Parameters/-1
Finde Zeilen mit /Syntax/
Implizit: Setze Zeile als aktuelle Zeile '.'
von dort bis Zeile vor Zeile mit /Syntax-Ende/
verschiebe vor Zeile mit /Parameters/
:g/>stream/ .+1,/endstream/-1 delete # Loeschen von Stream-Inhalten in PDF-Datei
:g/Chapter/ .+2w >> Hugo.txt (Haenge die jeweils 2-te Zeile nach Zeile mit "Chapter" an Datei Hugo.txt)
Zeile mit Muster wird implizit aktuelle Zeile '.'
:/Anfang/,/Ende/g/Chapter/ .+2w >> Hugo.txt (Haenge die jeweils 2-te Zeile nach Zeile mit "Chapter" innerhalb des Ranges Anfang-Ende an Datei Hugo.txt)
:/Anfang/,/Ende/g/Chapter/ .+2w >> Hugo.txt | .+1t$ (dito und kopiere die Folgezeile (also dritte Zeile nach Chapter-Zeile) ans Dateiende)
vor '|' ist aktuelle Zeile die zweite Zeile nach Chapter-Zeile
:g/Description/,/Parameters/-1d Alle Abschnitte von Description bis Zeile vor Parameters loeschen
:g/.*/mo 0 (Zeilenfolge umdrehen)
:g/^/mo 0 (Zeilenfolge umdrehen)
:v/\v^[[:digit:]]+/mo $ very-magic: Alle Zeilen, welche nicht mit einer Zahl beginnen, ans Dateiende verschieben
:g/\v^[^[:digit:]]/mo $ very-magic: Alle Zeilen, welche nicht mit einer Ziffer beginnen, ans Dateiende verschieben
Quantifier (fuer nicht very-magic)
\+ (1 oder mehrere)
\= (0 oder 1)
\{1,4\} (1 bis 4}
Wiederholung von Befehlen mit g: (Learning the vi and vim editors)
================================
Hintergrund: :[range]g(lobal){Muster}{Befehl}
Befehl muss sich nicht auf Trefferzeilen mit Muster beziehen !
:1,10g/^/ 20,27co $ (Kopiere Zeilen 20-27 10 mal ans Dateiende)
- Muster
<, > Word-Boundaries (zero-width-items)
\_ vorangestellt bedeutet "inkl. Zeilenende"
\_s+ (Whitespace inkl. Zeilenende)
/\v<(\w+)\_s+\1> very-magic-Suche nach doppelten Worten, durch Whitespace oder Zeilenende getrennt
:s entspricht :s//~/ (letztes Suchmuster und letzter Ersetzungs-String)
:s;/home/heinz;/home/anja;g # ';' als Delimiter anstelle '/'
Einfuegungen des substitute-commands (Replacement-String)
\1 \2 \0 (gesamter Treffer)
:10,20s/\v(that) or (this)/\u\2 or \u\1/g => This or That
\t \r
& == \0 (gesamter Treffer)
:%s/\v[[:alnum:]]+/\u&/g => very-magic: Kapitalisierung aller Wortanfaenge
:%s/\v[[:alnum:]]+/\U&/g => very-magic: Kapitalisierung aller Worte
:10,20s/.*/(&)/
~ vorheriges Ersetzungsmuster, d.h. Ersetzung durch Ersetzungs-String des vorherigen (!) Ersetzungsbefehls
:s/her/their/g
:s/his/~/g
\= Ersetzung durch VIM-Script-Ausdruck
%(..) zaehlt Klammer nicht mit fuer Back-References
:%s/\v(%(And|D)rew) (Neill)/\2, \1/g Vor- und Nachname vertauschen, wobei die innere Klammer nicht gezaehlt wird ('%' vorangestellt)
Look-Ahead und -Behind
/\v"\zs[^"]+\ze/ Suche nach Nicht-Anfuehrungszeichen innerhalb von '"' (zs: zero-start == look-behind ze: zero-end == look-after)
- Fenster
:set mouse=a (erlaubt Fensterunterteilungen per Maus zu aendern und Fenster per Maus zu aktivieren)
:set iskeyword? Werteliste fuer iskeyword anzeigen
:split,vsplit <Datei>
Ctrl-ws (== split)
Ctrl-wv (== vsplit)
Ctrl-w Ctrl-w
Ctrl-w(hjkl)
Ctrl-w <Pfeil>
Groesse aendern
Ctrl-w= (gleiche Hoehen und Breiten)
Hoehe
10 Ctrl-w _ (auf Hoehe 10 setzen)
10 Ctrl-w -
20 Ctrl-w +
:res -10
:res +10
:res 10 (Hoehe AUF 10 setzen)
Breite
10 Ctrl-w | (AUF Breite 10 setzen)
10 Ctrl-w <
15 Ctrl-w >
:vertical res 10
:vertical res -10
:vertical res +10
:close (Ctrl-wc)
:only (Ctrl-wo)
:help window-moving
:help window-resize
- Navigation
w,e,E,W,ge,b,B
iw,it,i",i{,ip
dito mit aw,at, ...
- z.B. daw, ciW
+,- (Zu Anfang der naechsten, vorherigen Zeile)
(,) (Anfang, Ende des aktuellen Satzes)
{,} (Anfang, Ende des aktuellen Paragraphen)
- Arithmetik
10 Ctrl-A
20 Ctrl-X
set nrformats-=octal (um aus 007 008 oder 006 zu machen; ist bereits Default)
- Register
:register / (Suchmusterregister anzeigen lassen)
a-z ueberschreiben
A-Z anhaengen
_ (Black-Hole)
" unnamed register (Default)
= expression register
: Letztes ex-command
% aktuelle Datei
# alternative Datei
/ letzes Suchmuster
Ctrl-r
======
Insert-Mode: Ctrl-r<register> Register einfuegen
Ctrl-r / letztes Suchfeld ausgeben
Ex-Mode :Ctrl-ra (Register a auf Command-Line einfuegen)
:Ctrl-r / letztes Suchfeld ausgeben
"ayw yank word in Register a
:%s/Ctrl-ra/Hugo/g Ersetze Inhalt von Register ueberall global
Ctrl-r= 10 * 20 (Arithmetik-Register einfuegen, d.h. Berechnungsergebnis ausgeben)
Cave: Punkt verwenden fuer Gleitkommarechnung, sonst nur Integerrechnung
Ctrl-r=20.5*3.7
:let i=5
Ctrl-r=i Variable i ausgeben
* (Middle-Mouse-Clipboard) und
+ (Clipboard)
:set noautoindent (empfohlen)
Cave: "+p unterdrueckt im Unterschied zu "*p autoindent und andere Optionen
"*yW Rest-Wort in Clipboard
"*yaW Gesamt-Wort in Clipboard
"*p Clipboard ausgeben
- Syntax-Highlighting
:syntax on
:set syntax (zeigt an, welches Highlightin genutzt wird)
:set syntax=html
:set filetype=html
Ctrl-L (Refresh Highlighting)
Iterierte Werte erzeugen
========================
:let i=1
qa
I Ctrl-R=i <Return> ) <Esc>
:let i=i+1 <Return>
q
<Zeilen markieren>
:'<,'>:normal @a
1)
2)
...
8)
Inhalte von Variablen anzeigen
==============================
2 Varianten
:echo &<var>
:set var?
Beispiele
:set path?
:echo &filetype
:set filetype?
:help runtimepath => Muster/Variablen des Suchpfades
:echo &runtimepath => Ausgabe des aktuellen Pfades
:echo &filetype => Dateityp der aktuellen Datei
:echo &iskeyword
:filetype => Ausgabe der Status zu filetype detection, plugin, indent
betreffend die folgenden Einstellungen in .vimrc
:set <option>! '!' am Ende => toggle current setting
:set ignorecase!
:set <option>& '&' am Ende => Default-Wert setzen
Spezifische Anweisungen fuer eigenen Dateityp
=============================================
.vimrc
filetype on (Default)
filetype plugin on
filetype indent on
.vim/filetype.vim
autocmd BufNewFile,BufRead *.dict set filetype=dictionary
Alternativ
.vim/ftplugin/dictionary/hugo.vim
oder
.vim/ftplugin/dictionary.vim
mit Inhalt z.B.
set sw=8
Dictionary bekanntmachen und Wort-Trenner dafuer hinzufuegen (da sonst Umbruch an diesen Stellen)
=================================================================================================
.vimrc
set complete+=k Default: .,w,b,u,t,i <= nun auch mit "k" fuer Dictionaries (Ctrlx Ctrl-k)
set dictionary+=~/.vim/heinz.dict
set iskeyword+=-,/ <= Erweiterung der Wortzeichen, falls "/" und "-" in Dictionary vorkommen
Cave: Danach werden "-" und "/" als Wortbestandteile und nicht mehr als Worttrenner
gewertet
Cave: Jede Zelle kann gleichzeitig sowohl ein Label/einen String ALS
auch einen numerischen Wert enthalten. In alle Zellen koennen
"parallel" Strings und numerische Werte eingegeben werden.
Dies ist wichtig bei @ext(se,e),
da 'e' (expression) ein numerischer Wert sein muss, welcher als Argument
fuer den Aufruf von 'se' (string expression == command-line) in einen
String gewandelt wird. Nicht moeglich ist daher, fuer 'e' auf den
Label-Teil einer Zelle zu verweisen !
Cave: In *.sc Dateien stehen die Kommandos fuer Zellen in der eigentlichen (Lang-)Form.
Diese Form ist zu verwenden fuer
Macros
=> *.sc-Dateien koennen als Macro-Dateien-/Vorlagen genutzt werden
cf. die (nur in der Man-Page dokumentierten) Befehle
R(un)
A(utoexecute)
D(efine)
Definition von Funktionstasten <F2>, <F3>, ...
Die in einer sc-Sitzung eingegeben Kurzformen sind Shortcuts, welche
in den Eingabemodus wechseln und in diesen (transparent) die eigentliche Langform eingeben
cf. Man-Page
the single key commands are shortcuts which switch to input mode after first entering the beginning of the full command for you
Command-Line
============
Cave: -P behaelt Formatierungen NICHT bei
sc -P A0:G20/A30 Datei.sc > Auszug_verschoben.sc
Kopiert Range A0 bis G20 in neue Datei, jedoch beginnend in Feld A30 (cf. unten)
sc -P A0:G20/A30 Datei.sc >> Vorhandene_Datei.sc
dito, jedoch Verschmelzung mit anderer sc-Datei
sc -v -P A0:M126 Datei.sc > Auszug_nur_mit_Werten.sc
Kopiert Range A0 bis M126 und wandelt dabei alle Ausdruecke/Formeln in Werte
sc -v -P % Datei.sc > Auszug_Gesamtdatei_nur_mit_Werten.sc
dito mit Pseudo-Range der Gesamtdatei
sc -W A0:M126 Datei.sc > Bildschirm-Abbild.txt
Erzeugt reine Textausgabe des angegebenen Ranges wie in sc-Sitzung auf dem Bildschirm dargestellt (also mit dortiger Formatierung)
sc -W % Datei.sc > Gesamte_Datei_als_Bildschirmabbild.txt
dito mit Pseudo-Range der Gesamtdatei
Zweite Datei laden
==================
M (Merge)
=> Eingabefeld oben links
| sc -P %/A100 Hugo.sc
piped/inkludiert den gesamten Inhalt aus Hugo.sc (Angabe % anstelle Ranges) ab Zelle A100 des aktuellen Dokumentes
Befehle
=======
<F1> man sc
cf. auch
fkey n = "command"
G(et database from file) <= aktuelle Datei wird ueberschrieben
M(erge database into current file)
M /home/heinz/.scrc
laedt diese Datei hinzu
Tipp: Vorher Ausschnitt und neuen Startpunkt der neu zu ladenden Datei festlegen mit
sc -P A0:G50/A101 Datei_2.sc > Datei_2_Ausschnitt.sc
Editieren und Zeilenbreiten (ggf. auch Farben) anpassen
In Datei_1 (welche auf Zeile 99, also 2 Zeilen ueber dem neuen Startpunkt der Ausschnittdatei endet):
M Datei_2_Ausschnitt.sc
$K$20
Zellangabe fix
P <Datei> Speichern
ZZ Speichern und verlassen
W <Datei> Speichern des Bildschirmabbildes
W "Hugo.txt" AL0:AV18 Speichern des Bildschirmabbildes eines Range
T => table-output gemaess Wert von tblstyle, z.B. CSV speichern mit ':'-Delimiter (cf. unten)
Beispiel
S
set tblstyle=latex
T "" E2:I7
speichert Range E2:I7 mit Defaultnamen und Endung .latex
Cave: Erster " wird von sc gesetzt, zweiter ist zu ergaenzen, danach <TAB> fuer Range-Eingabe
~/.scrc: Konfigurationsdatei
Definition der Default-Dateiendungen uber
scext
ascext
tbl0ext
tlbext
latexext
slatexext
texext
Beispiel
========
scext "sc"
ascext "txt"
tbl0ext "csv"
tblext "tbl"
latexext "latex"
slatexext "slatex"
texext "tex"
set color
#---------------------------------------------------------------------------
# Nach Return zu Zelle darunter
# craction=1 nach unten
# craction=2 nach rechts
# ^t r <Pfeiltaste in gewuenschte Richtung> => Toggle des Return-Verhaltens
#---------------------------------------------------------------------------
set craction=0
format 5 = "0,.&"
format 6 = "0,.& Eur"
format 7 = "0,.& L"
#---------------------------------------------------------------------------
# Function Keys
# $$ ist die aktuelle Zelle => fuer Range-Angabe verdoppelt
#---------------------------------------------------------------------------
fkey 2 = "color $$:$$ 1" # Zellfaerbung zuruecksetzen
fkey 3 = "rightstring $$ = @ext(\"dateutils.ddiff \"#A1#\" \"#A2#\" #\",0)"
#---------------------------------------------------------------------------
# Alternative, wenn neg. Zahlen in Klammern dargestellt werden sollen
#---------------------------------------------------------------------------
# format 5 = "0,.& Eur;(0,.& Eur)"
# format 6 = "0,.&;(0,.&)"
#---------------------------------------------------------------------------
# Farben
# Cave: color 2 ist Farbe fuer negative Zahlen, wenn deren Kennzeichnung mit
# ^TN
# S colorneg
# gesetzt ist
#---------------------------------------------------------------------------
color 1 = @black;@white
color 2 = @yellow;@white
color 3 = @blue;@white
color 4 = @green;@white
color 5 = @red;@white
color 6 = @magenta;@white
color 7 = @cyan;@white
Navigation
==========
^e(jklm) => zur naechsten (nicht-)leeren Zelle oben,unten,links,rechts
je nachdem, ob die aktuelle Zelle leer oder nicht-leer ist
0 erste Zelle der Reihe
$ letzt Zelle der Reihe
^ Oberste Zeile
# Unterste Zeile
j,k,l,m == Pfeiltasten
^Y und ^E Bildschirm 1 Zeile nach unten, oben
g B100 Gehe zu Zelle B100
^A => Gehe zu Zelle A0
^L Display neu aufbauen/Schirm neu zeichnen
z.B. nach ^X zur Anzeige von Formeln in Zellen mit Ueberlapp in Nachbarzellen
w analog vim => naechster Wortanfang (== naechste gueltige Zelle)
b analog vim => dito vorherige gueltige Zelle
^t Toggle Options
a automatische Neuberechnung
=> explizite Neuberechnung mit '@'
C (toggle Color)
N (toggle Color fuer negative Zahlen => Farbpaar 2)
E (toggle Color fuer fehlerhafte Zellen)
r <Pfeiltaste> (toggle Bewegung nach Return)
c Cell-Highlighting (Highlighting vs. <=)
s colorslop => String, welcher laenger als aktuelle Zelle ist, auch dann in Nachbarzelle ueberlappen, wenn diese anderem Farbrange angehoert
n quick numeric entry (Eingabe von Zahlen ohne "=")
S Set Options => Menue oben; jedoch nur Teilauswahl der Optionen der Manpage, besser als Auswahl ist Direkteingabe
locale # Tausendertrennzeichen und Dezimalpunkt (nicht ueber ~/.scrc zu erreichen :-/)
Einstellung wird nicht in Datei gespeichert und ist daher nur temporaer, aber
W <datei>
uebernimmt die temporaeren locale-Formatierungen als Textdarstellung des aktuellen Bildschirmes
color
cslop (funktioniert scheinbar nicht als Eintrag in Konfigurationsdatei .scrc)
Ueberlapp eines String in Nachbarzelle, welche anderem Farbrange angehoert
Cave: Bei ^T S cslop
wird in der Datei folgendes eingetragen
set cslop tblstyle = latex color
craction=0,1,2
tblstyle=
0 <= entspricht CSV-Ausgabe mit ':'
delimiter ':'
tbl
delimiter ':'
latex
delimiter '&'
slatex
Scandinavian Latex
tex
delimiter '&'
frame
Framemaker
@ Neuberechnung (z.B. falls automatische Neuberechnung mit ^ta deaktiviert wurde)
mx Markiere Zelle durch Puffer x
'x springt wieder zu Zelle (analog vim)
cx Kopiert zuvor mit mx markierte Zelle
c. Kopieren Range => Range:
c. <Target-Range-Angabe mit Cursor> <TAB> (Uebernahme markierten Target-Ranges) <TAB> <BACK> <Ueberschreiben> Angabe des Source-Range
"x Naechstes yank/delete/pull-Command in Buffer x
"ary <rangeauswahl mit Pfeiltasten>
Range in Buffer a kopieren
"app
zuvor in Buffer a kopierten Range ausgeben
Achtung: Zellreferenzen werden NICHT aktualisiert im Unterschied zu
rc <dest> <src>
z<Ret> Zeile wird erste Zeile des Bildschirmes
z. Zeile wird mittlere Zeile des Bildschirmes
z| Spalte wird mittlere ...
zc Zelle wird Bildschirmzentrum
= Zahleneingabe
><\ Stringeingabe rechts, links, zentriert
mit '"' beginnen, Abschluss-'"' wird automatisch gesetzt
Beginnt der String selbst mit '\' wird das folgende Zeichen als Fueller der Spalte verwendet
>"\- => "------"
<"\- => "------"
\"\- => "------"
Cave: Hier muss das schliessende Hochkomma wegen des Whitespace manuell gesetzt werden
>"\+ " => "+ + + + "
{|} String ausrichten links, rechts, zentriert
F Zelle formatieren (cf. auch rF unten)
F A8:A8 "0.00 Eur"
F A8:A8 ",0 Eur" (mit Tausendertrennzeichen)
F A8:D8 "0 %"
F A8:D8 "0.0000"
F D7 "0 m3"
Es kann hier auch ein Range eingegeben werden
F B4:B8 "#,0.& \Liter"
zu lesen als
Zahl vor Tausendertrennzeichen
mit mindestens einer 0 vor dem Dezimaltrenner '.' und
danach so viele Zeichen wie Zellvorgabe fuer Dezimalstellen
0.01 ergibt (bei Zellvorgabe zweier Dezimalstellen) bei
#,0.& => 0.01
#,.& => .01
.& => .01
# Zahl
0 Zahl mit 0-Padding
. Dezimalpunkt
% Prozentzahl durch Multiplikation mit 100
z.B. Eingabe
= 0.025
rF <Bereichsauswahl> <Tab>
"0.00 % (Formatierungsangabe mit %)
=> Anzeige: 2.5 %
, Tausendtrenner
& Nachkommastellen werden mit 0 aufgefuellt, bis Zellvorgabe fuer Dezimalstellen erreicht
\ Quotierung des naechsten Zeichens
; Eingabe getrennter Formate fuer positive und negative Zahlen
Datumsformatierungen mit den Symbolen aus 'man strftime' und vorangestelltem Ctrl-D, also etwa
FCtrl-D%F => angezeigt als "^D%T" (z.B. fuer Inhalt =@dts(2021,12,31) => Ausgabe als 2021-12-31
Cave: Formatierter Datumswert erscheint so immer linksbuendig, also besser so eingeben
FCtrl-D %F
angezeigt als "^D %F"
sinnvoll in .scrc
entweder
fkey 5 = "fmt $$ \"^D%F\""
oder mit der vorigen Anmerkung
fkey 5 = "fmt $$ \"^D %F\""
Cave: CTRL-D muss in vim "verbatim" eingegeben werden via CTRL-V CTRL-D und erscheint dann in blauer Schrift als ^D
Datumsfunktionen
================
Cave: Alle Datums-/Zeitfunktionen ausser @date liefern numerische Werte
=> Bei @date String-Eingabe (<>\) fuehrendes, automatisch gesetztes '"' loeschen wie immer bei String-Formeln, da sonst literal interpretiert
@date(@dts(2022,01,01),"%F") => 2022-01-01
cf. man strftime fuer zulaessige %-Werte
2022.01.01 wird als Schnelleingabemoeglichkeit konvertiert zu @dts(2022,01,01) (aber nur, wenn als Zahlenwert eingegeben !)
=2022.01.01 => @dts(2022,01,01)
zusaetzliche Belegung des Label-Feldes moeglich mit
>"2022.01.01
=> kombiniert in Feld links oben: "2022.01.01" [@dts(2022,01,01)] (in Zelle dargestellt wird String, Epoc-Sekunden sind in numerischem Feld)
Beispiele
A0: =@dts(2022,1,1) => 1640991600
A1: =@dts(2022,1,31) => 1643583600
A2: =A1-A0 => 2592000
A3: >@date(@dts(2022,1,1),"%F") => 2022-01-01
A4: >@date(@dts(2022,1,1)+A2,"%F") => 2022-01-31
A5: =A2/(60*60*24) => 30 (Abstand in Tagen zwischen 01.01. und 31.12.2022)
B1: >@date(A1,"%F") => 2022-01-31 (Formatierungsfunktion)
B1: F CTRL-D%F (implizite Formatierung als Datum 2022-01-31)
Cave: Moeglich ist
Schnelleingabe
A0: =2022.01.01 => [@dts(2022,01,01)] mit Anzeige des numerischen Feldes in Epoc-Sekunden, z.B. 123456
A0: >@date(A0,"%F") => >{@date(A0,"%F")} [123456]
Formel aus numerischem Feld wird durch Epoc-Sekunden ersetzt, angezeigt wird der String 2022-01-01
aber: anschliessende Aenderung des numerischen Feldes durch z.B.
=2022.01.31 => >2022-01-01 [@dts[2022,01,31)]
macht wiederum den String konstant (mit dem vorigen Wert), d.h. man kann nur in entweder dem
numerischen oder Label-Feld eine Formel unterbringen. Diese wird sofort in Wert umgewandelt, sobald
das jeweils andere Feld eine Formel erhaelt.
# konkateniert Strings
A1#A2
"Hugo "#B17
<>\"\- Fuegt durchgehende Linie in Zelle ein
Zr zap row
6Zr 6 Zeilen ausblenden
Zc zap column
sr show row <Auswahl>
sc show column <Auswahl>
<Zahl>f Spalten formatieren (Breite, Dezimalstellen, Formatierungsnummer)
Pfeil links/rechts => Spaltenbreite (alternativ: h,l)
Pfeil auf/ab => Dezimalstellen (alternativ: j,k)
<Zahl> => Formatnummer (cf. unten)
(h,j,k,l oder Pfeiltasten, numerische Tasten fuer Formatierungsnummer)
0 Fixed
1 scientific
2 engineering
3 dates (Jahr 2-stellig)
4 dates (Jahr 4-stellig)
5-9 eigene vordefinierte Formate (cf. f=<Zahl>)
<Zahl>f<Blank> wie oben, jedoch mit Editierung der Formatangaben in der obersten Zeile
f=<Zahl> Definition des Spaltenformates <Zahl>
Formatierungsangaben wie unter F
Beispiel: F "#,0.& \Eur" <RETURN>
Tipp: Format kann nach Ctrl-C mit Shift-Ins eingefuegt werden
Beispiel: f= (Auswahlmenue 0-9 erscheint) 5 "#,0.& ;(#,0.&)"
^x Formeln aller Zellen anzeigen
^r Anzeige aller Zellen mit numerischen Werten OHNE Formeln
g H3 => "go" H3
e Zahl editieren
E String editieren
Zeilen- und Spaltenkommandes (optional: Zahlangabe vorher)
ir,ic (insert row, column)
4ic (4 Spalten einfuegen)
ar,ac (Aktuelle Zeile, Spalte kopieren "append")
5ar 5 mal die aktuelle Zeile kopieren
dr,dc Beispiel: 5dr
or,oc
dd Aktuelle Zeile loeschen
x Aktuelle Zelle loeschen
yr,yc,yy (yank row, colum, cell - Abfolge: yr => pr; yy => pp oder pf; yc => pc)
2yr 2 Zeilen kopieren
pr (vorige) 2 Zeilen einfuegen
3yc 3 Spalten kopieren
pc (vorige) 3 Spalten einfuegen
pr,pc,pp == pull row, colum, cell
pC (wie pp, aber Aenderung der Zell-Referenzen)
p. (wie pC, aber mit Cursor-Auswahl des Ziel-Ranges)
=> beliebig viele Kopien genau EINER Quell-Zelle in Ziel-Range
Cave: Funktioniert nicht mit mehr als einer Quell-Zelle
Beispiel
yy <Return>
p. <Range mit Cursor markieren> <Return>
=> n Kopien der kopierten Zelle
pm (mergen statt einfuegen)
ueberschreibt in Zielzelle bei zuvor kopiertem String nur deren String-Wert,
waehrend ein numerischer Wert in der Zielzelle beibehalten wird
pf (genau und nur Formatierung mergen nach z.B. vorherigem yy)
Cave: Farben gehoeren NICHT zur Formatierung
Formatierung ist ein zuvor mit F oder rF gesetztes Format der Quellzelle/des Quell-Range
die mit f festgelegte Formatierung der Quell-Spalte wird NICHT in die Ziel-Spalte uebertragen
px (exchange Quelle (Delete-Buffer) und aktuelle Zelle)
pp (paste)
Cave: Zell-Referenzen werden NICHT updated => bei Zellbezuegen pC verwenden
vr,vc,vv Formeln in (je nach Ausgabeformat der Zelle(n)) Strings oder Zahlen wandeln
Zr,Zc,ZZ Ausblenden
sr,sc Einblenden
Range-Commands: links oben (in Zielrange) positioneren, Kommando eingeben, Range mit Pfeiltasten auswaehlen und <TAB>
Tipp: Anstelle Cursorbewegung oder expliziter Eingabe 'A10:A40' koennen auch Wiederholung und Richtung angegeben werden (10j, 5l, 3h, ...)
Beispiel: rf 10l <TAB> 10 1 <RETURN>
range fill => 10 Zellen ab 10, inkrementiert um 1
Beispiel: rf 10l <TAB> Hugo 0 <RETURN>
increment '0' bewirkt Fuellung mit identischem Wert fuer alle Zellen
Cave: Fuellt numerisches Feld, nicht Textfeld !
rx Range loeschen => p-Kommandos
ry Range yank (Referenzen fix) => p-Kommandos
Range-Angabe ist der zu kopierende Range
ry 5l
ry <Cursor-Auswahl>
ry <TAB> <BACKSPACE> <ueberschreiben>
rc Kopiere Destination-Range <= Source-Range
Quelle kann einzelne Zelle sein => Range A2:A2
Besonderheit: Zell-Bezuege werden aktualisiert (cf. pp vs. pC oben)
Vorgehen
aktuelle Zelle wird als destination range vorbelegt, destination range kann mit
- Cursorbewegung <RETURN>
vergroessert werden
Source-Range-Angabe danach mit
- <TAB> <BACKSPACE> [ueberschreiben], z.B. <TAB><BACK> C4:H4 <RETURN>
rm fast wie rc, aber 'move'
Vorgehen 1
Links oben in Zielrange positionieren
rm <Tab> <Tab>
Ergaenzung des zweiten <TAB> mit Quellrange ueberschreiben (C17:C26)
<RETURN>
Vorgehen 2 (optimal)
Links oben in Zielrange positionieren
rm (Target-Range (einzelnes Feld) wird eingetragen
mit Cursor in erste Zelle des Quell-Range wechseln
<TAB>
mit Pfeiltasten Quell-Range markieren
<Return>
:-)
rr range-range (outrange und innerrange) => "freeze"
outrange beinhaltet innerrange
die "Differenz" wird nicht scrolled
Auswahl der Range-Art mit Anfangsbuchstaben der Auswahlliste nach rr <TAB>
hier: a(ll) auswaehlen oder l,t,r,b
rr a(all) <TAB> A0:Z100 A1:Z100
friert die oberste Zeile ein und erzeugt den Dateieintrag
frame A0:Z100 A1:Z100
rr l A0:Z100 1
friert die aeusserst linke Spalte ein
Cave: "freeze" funktioniert nur, sofern bei Scroll der innere Range NICHT verlassen wird
=> immer Range definieren, welcher mehr Zellen umfasst als auf Bildschirm dargestellt
einen outer-range A0:Z1000 kann man sich auch besser merken fuer unframe-command
rv Formeln in Zahlen wandeln
rd Range definieren (Bezeichner kann danach anstelle des Ranges verwendet werden)
Cave: Zuvor mit ^T l Autolabelling disablen
andernfalls wird Range-Name in (leere) Zelle links daneben geschrieben und in Datei als z.B.
label C4 = "hugo"
gespeichert
rd "Wartung" AB10:AF73
rd "Wartung"<TAB> <Range-Auswahl mit Cursor-Tasten>
g "Wartung" => AB10
rc F17 Wartung
Ranges werden in Datei gespeichert als
define ...
ru Rangedefinition loeschen
rs Sortieren mit Angabe von 3 Parametern
Cave: Sortiert werden kann nur die Zeilenabfolge
Vorgehen
Links oben im Range positionieren
rs (ggf. mit Pfeiltasten markieren und) <Tab>
Rangeangabe vervollstaendigen (eintippen, springen oder mit Pfeiltasten markieren)
optional: Sortieranweisungen in "..." eingeschlossen (auch mehrere Spalten nacheinander)
1.) + oder -
2.) # oder $ (# fuer numerisch, $ fuer String)
3.) <Spalte innerhalb Range, nach welcher sortiert wird>
Default ist "+$", also alphabetisch aufsteigend
Beispiel:
rs <Pfeiltasten Range markieren> <Tab> "-$A" <RETURN>
rs <Tab><BACK> A1:D10 "+#B" <RETURN>
rs <TAB><BACK> A1:A10 <RETURN>
rs <TAB><BACK> A1:D10 "-$A+#B"
zuerst alphabetisch absteigend nach A
danach numerisch aufsteigend nach B
rs <TAB><BACK> A1:D10 "+$A+#A"
entweder alphabetisch oder numerisch aufsteigend in A
rf Range fuellen
Vorgehen
rf
Range mit Navigationstasten markieren
<TAB>
Startwert
Inkrement
<RETURN>
Beispiel:
rf <Pfeiltasten> <Tab> 10 5 <Return>
rf 10j <Tab> 10 5 <RETURN>
r{ Range ausrichten
r}
r|
rS Rangedefinitionen anzeigen (z.B. auch Farbwerte)
rF Range formatieren
Rangeauswahl mit Pfeiltasten
<Tab>
Formatangaben wie unter F
Beispiel: rF <Pfeiltasten> <Tab> "#,0.& \Eur" <RETURN>
Tipp: Format kann nach Ctrl-C mit Shift-Ins eingefuegt werden
rC Farbrange anlegen
Rangeauwahl wie immer (Links oben positionieren, Pfeiltasten, <TAB>)
gefolgt von Farbnummer (1-8) und
<RETURN>
rd Range definieren
rd "Name" <TAB> Cursor bewegen oder Range eingeben (Backspace + Ueberschreiben)
g <Name> springt zu definiertem Range
rS Range-(und andere) Definitionen anzeigen
ru Range entdefinieren
ru "Name"
Farben
rS u.a. alle Farbdefinitionen anzeigen
1 ist immer Defaultfarbpaar
2 Farbe fuer negative Zahlen, wenn colorneg gesetzt
S colorneg oder
^TN
3 Farbe fuer fehlerhafte Zellen
S colorerr
^TE
4 Farbe fuer Felder mit Notizverweisen
C Farbdefinition fuer Auswahl aus 1-8 setzen
ohne Formatangabe => loeschen der Farbdefinition
Formatangabe: @white;@green (Vordergrund und Hintergrund)
falls bereits Format definiert war, wird dieses zur Editierung angezeigt
Defaultfarben
color 1 = @white;@blue
color 2 = @red;@blue
color 3 = @white;@red
color 4 = @black;@yellow
color 5 = @black;@cyan
color 6 = @red;@cyan
color 7 = @white;@black
color 8 = @red;@black
Notizen
*a legt Link zu Zielzelle (mit Kommentar an)
Angabe der Zielzelle wie immer mit <TAB> <TAB> <BACK> Ueberschreiben
Cave: Ist das Feld numerisch, wird ein * als Kommentarkennzeichen in Farbe 4 vorangestellt
** springt zu Zelle mit Kommentartext
'' Ruecksprung zu Ausgangszelle
*d Kommentarverweis loeschen
*s zeigt Zellen mit Kommentarverweis durch Kontrastfarbe
Funktionen/Formeln
==================
Fuer alle elementar und wichtig:
~e ist Verneinung eines Ausdruckes e
Elemente einer Formel koennen entweder Strings oder numerische Werte sein
demgemaess muessen Werte und Zellbezuege innerhalb von Formeln ggf. zu Strings oder numerischen Werte gewandelt werden
@ston(A17)
@fmt("%.sf",B101)
Das Ergebnis einer Formel kann entweder ein String oder numerischer Wert sein
demgemaess muss bereits die Formel selbst entweder als numerischer Wert oder String eingegeben werden
=@if(....) => Ausgabe in numerisches Feld der Zelle
>@if(...) => Ausgabe in String-Feld der Zelle
Damit die Formel selbst als solche und nicht Text interpretiert wird, muss das von sc automatisch zu Beginn
der String-Eingabe eingefuegte Hochkomma zunaechst geloescht werden, also
@if(...)
und nicht
"@if(...)
>@sval("D",0) => Uebernahme des Labels aus D0
und nicht >"@sval("D",0)
@sum
====
Bedingte Summierung (wie auch andere bedingte Funkionen)
Falls der Bedingungsausdruck sich auf eine andere Spalte bezieht, wird genau und nur deren oberste Vergleichszelle angegeben.
Die untere Vergleichszelle ergibt sich aus der Summationsspalte
@sum(A0:A3) <= unbedingte Summation von A0 bis A3
@sum(A0:A3,@eqs(B0,"ja")) <= bedingte Summation von A0 bis A3, sofern Bedingung jeweils in B0 bis B3 erfuellt ist
@sum(A0:A3,~@eqs(B0,"ja")) <= bedingte Summation mit Verneinung ('~' ist boolsches Nein)
A B
0 1.0 <- Beginn der bedingten und unbedingten Summation
1 2.0 "ja"
2 3.0 "ja"
3 4.0 <- Ende der bedingten und unbedingten Summation
4 5.0 "ja" <- wird nicht mehr bedingt summiert
5
6 =@sum(A0:A3) =@sum(A0:A3,@eqs(B0,"ja"))
=> 9 5
A7: 10.5
Eingabe: >@fmt("zu viel %10.2f",A7) => "zu viel 10.5"
Cave: Eingabe mit ">", da String-Funktion
@sum(A0:A9,A0>5)
@sum(A0:A9,A0=5) numeric equality <=> @eqs(A0,"ok") string equality
summiert alle Zellen von A0 bis A9, welche jeweils (!) groesser/gleich 5 sind
Externe Funktionen
==================
@ext(se,e)
se=string expression
e=(numerical) expression
se: Erster Teil der Kommandozeile: muss String oder Verkettung von Strings sein (oder Bezug auf String-Wert einer Zelle)
e: Zweiter Teil der Kommandozeile: muss numerischer Wert sein (oder Bezug auf numerischen Wert einer Zelle) und wird implizit zu String gewandelt
Cave: Dennoch ist NICHT moeglich, gleich einen String anzugeben oder auf den String-Wert einer Zelle zu verweisen
Der Trick ist daher, den gesamten Aufruf in Teil 1 als Verkettung von Strings zu verpacken und diese Kommandozeile mit
dem Bash-Kommentarzeichen '#' so abzuschliessen, dass Teil 2 nur als Kommentar in den Gesamtaufruf kommt
(cf. hierzu auch 'man sc')
Cave: Das Konkatenierungszeichen fuer sc ist ebenfalls ein '#' ;-)
Beispiele
=========
Beispiel 1
==========
Konkatenierung von Strings
#######################Externe Funktion ist ein Bash-Script###############################
#!/bin/bash
#-------------------------------------------------------------
# Test-Script mytest
#-------------------------------------------------------------
printf "Arg1: (%s) Arg2: (%s)\n" "$@"
#######################Externe Funktion Ende##############################################
Cave: Im folgenden ist '#' das sc-Konkatenierungszeichen UND das Bash-Kommentarzeichen vor dem damit auskommentierten zweiten Teil der Kommandozeile '0'
Cave: Das Ergebnis von @ext ist wiederum ein String, KEINE Zahl !
Anschliessend daher mit @ston in Zahl wandeln (wenn mit dem Ergebnis weitergerechnet werden soll)
Cave: Wandlung in EINEM Schritt, d.h. Zahlausgabe in die Zelle mit der @ext-Formel, scheint nicht moeglich
A B C D
1 2021-01-01 2021-01-31 @ext("mytest "#A1#" "#B1#" #",0) => Arg1: (2021-01-01) Arg2: (2021-01-31)
2 2021-01-01 2021-06-31 @ext("dateutils.ddiff "#A2#" "#B2#" #",0) => 180 (String)
3 2021-01-01 2021-06-31 @ston(@ext("dateutils.ddiff "#A3#" "#B3#" #",0)) =@ston(C3)/2 => 180 (String) => 90 (Zahl)
Beispiel 2
==========
Konkatenierung von Strings und numerischen Werten
#######################Externe Funktion ist ein Bash-Script###############################
#!/bin/bash
#-----------------------------------------------------------------------------------------
# Externe Funktion fuer sc-Tabellenkalkulation: myscsollcell
#-----------------------------------------------------------------------------------------
. /usr/bin/common # fuer Funktion 'calc'
steuerKonto=$1
buchung=$2
if [[ "$steuerKonto" =~ ^[0-9]+$ ]]; then
case "$steuerKonto" in
1568) printf "%s\n" $(calc "$buchung / 1.05" 2 2) ;;
1571) printf "%s\n" $(calc "$buchung / 1.07" 2 2) ;;
1575) printf "%s\n" $(calc "$buchung / 1.16" 2 2) ;;
1576) printf "%s\n" $(calc "$buchung / 1.19" 2 2) ;;
1771|1773|1775|1776) printf "%s\n" $buchung ;;
*) printf "%s\n" 0 ;;
esac
else
printf "%s\n" 0
fi
#######################Externe Funktion Ende##############################################
A B C
0 Konto Buchung
1 1568 100.0 @ext("myscsollcell "#A1#" "#@fmt("%.2f",B1)#" #",0)} <= Verkettung wie in Beispiel 1, jedoch Wandlung von B1 in String => ergibt 95.23 (= 100.0/1.05)
Cave: Vor Duplizierung von @ext-Formeln
mit (Toggle-Befehl)
^ta
Auto-Aktualisierung ausschalten (sonst Core-Dump)
rc-Befehl ausfuehren
Ergebnis editieren
mit
@
alle Berechnungen aktualisieren
und Auto-Aktualsierung wieder einschalten
Alternativen: Formel als Text kopieren mit STRG+SHIFT+C und wiederholt einfuegen mit SHIFT+EINF (und editieren)
Cave: Vor Einfuegen in Eingabefeld links oben automatisch eingefuegtes '"' loeschen !
Tipp: Text als Hotkey belegen (cf. unten)
fkey 5 = "rightstring $$ = @ext(\"dateutils.ddiff \"#A1#\" \"#A2#\" #\",0)"
@if-Anweisungen
===============
Falls Stringausgabe:
Numerischer Vergleich
@if(C126=100,"Dr. Breinlinger","Sonst jemand")
String-Vergleich
@if(@eqs(C126,"Heinz")?"Dr. Breinlinger,"Sonst jemand")
Falls numerische Ausgabe:
Numerischer Vergleich
=@if(C126=100|C126=50,1,2)
String-Vergleich
=@if(@eqs(C17,"Passt"),1,2)
Alternative via Operator e?e:e @eqs(C126,"Heinz")|@eqs(C126,"Willi")?1:2
Cave: Rekursionen sind nur durch Klammern des jeweils gesamten Else-Zweiges einer jeden Rekursion moeglich:
Beispiel
========
Falls Feld G304 die String-Werte "1568","1571","1575","1576" annimmt: Jeweils verschiedenen Berechnungen
( Else-Zweig 1 ( Else-Zweig 2 ( Else-Zweig 3 )))
@eqs(G303,"1568")?D4/1.05*0.05:(@eqs(G303,"1571")?D4/1.07*0.07:(@eqs(G303,"1575")?D4/1.16*0.16:(@eqs(G303,"1576")?D4/1.19*0.19:0)))
Programmierbare Funktionskeys
=============================
fkey <nummer> = "command"
in ~/.scrc oder *.sc oder auf command-line
command ist (genau und nur) JEDE (!) Anweisung, wie sie auch in einer *.sc-Datei vorkommt
$$ bezeichnet die aktuelle Zelle => fuer Range-Angabe also verdoppeln (A2 => A2:A2)
Beispiele
fkey 2 = "color $$:$$ 1" <= "entfaerbt Zelle", sofern Farbe 1 schwarz/weiss darstellt
fkey 9 = "fmt $$ \""0,.& Eur\""
fkey 4 = "let $$ = @myrow"
fkey 5 = "rightstring $$ = @ext(\"dateutils.ddiff \"#A1#\" \"#A2#\" #\",0)"
=> erzeugt natuerlich, so die Dummy-Zellwerte A1,A2 keinen Datums-String beinhalten, eine Fehlermeldung
und ist nach Eingabe ueber <F5> schlicht mit E zu editieren :-)
Macros
======
cf. Anmerkungen zu Beginn
R *.sc-Datei
fuehrt Befehle der eingelesenen *.sc-Datei aus
R Macro.sc
A *.sc-Datei
laedt *.sc-Datei bei naechstem Start der aktuellen Datei automatisch
A Macro.sc
D <Macro-Verzeichnis>
Definiere Verzeichnis fuer mit R oder A angegebene Macro-Dateien
Vermischtes
===========
CTRL-X zeigt alle Zellen mit numerischen Werten, welche aus Formeln resultieren
CTRL-R ist das genaue Gegenteil => Anzeige aller Zellen mit numerischen Werten OHNE Formeln
=> Anzeige aller in einem Formular AUSZUFUELLENDEN Zellen :-)
g <suchbegriff oder zelle>
Cave: Alle in "" eingeschlossenen Suchbegriffe sind regular expressions
Gesetzt werden muss wie immer nur der ersten '"'
Cave: Pattern muessen nur Teil-String matchen
Cave: Mustersuchen bei Zahlen mit
g #"
beziehen sich immer auf das dargestellte
Ergebnis, d.h. auch Formelergebnisse werden damit gefunden
Cave: Mustersuchen mit
g %"
beziehen sich immer auf die Formeldarstellung
Cave: Regulaere Ausdruecke immer analog ed (Vorlaufer vi(m)s)
========================================================================
g a14 => Zelle mit Koordinaten
g 10.7 => Zelle mit dieser Zahl
Cave: gesucht wird nach diesem Zahlwert, nicht einer formatierten Zahl-Darstellung
g "Abschlaege => Zelle mit diesem regulaeren Ausdruck
g #"6,362 kg => Suche nach formatierter Zahl (verstanden als regulaerer Ausdruck
der formatierten Zahldarstellung)
g #".*15.* => findet >2,150.43< ebenso wie >115.61 Eur/mon<
Cave: g #"42" => findet alle direkt eingegebenen oder errechneten Zahlen, welche
"42" ENTHALTEN !
Cave: g #"2150 => findet mit Tausendertrenner dargestellte Zahl "2,150" NICHT
=> es wird immer nach der FORMATIERTEN Darstellung gesucht
g #".72 => sucht nicht nach <Komma>72, sondern
beliebige Ziffer, gefolgt von 72
g #"8.*% => findet z.B. '82 %','62.81 %",
g %"T32 => Suche nach Zelle mit Formel, welche T32 beinhaltet (==referenziert)
g %".*B.*" => Suche nach Zellformeln, welche ein 'B' beinhalten
=B6
=12*B7
g "^.*Vita.*$ => Suche mit regulaerem Ausdruck
n => Wiederholung der Suche/nachesten Treffer anzeigen
g<return> => Widerholung der letzten Suche (analog n)
! <Return> => Shell beginnen .. Abschluss mit exit und "press any key to continue ..."
! ls => Shell Befehl ausfuehren
psc (prepare (data for) sc)
===========================
Cave: Integer werden als Zahlen erkannt; Gleitkommazahlen nur, wenn Dezimaltrenner ein '.'
ist (und andernfalls als String interpretiert).
dos2unix Master.csv
psc -C2 -k -d\; < Master.csv > Master.sc
-C2 : Spaltenbreite 2 Stellen weiter als fuer breitesten Eintrag noetig
-k : keep all delimiters => leere Zellen nicht verwerfen
-d\;: Delimiter ;
Alternative (mit automatischer Wandlung deutscher Gleitkommazahlen): mycsv2sc
Export zu csv
=============
Export als csv-Tabelle mit (innerhalb sc-Sitzung)
S tblstyle=0
als Default bereits eingestellt und als solches nicht in *.sc sichtbar
(jedoch aus .scrc uebernommen)
T
Export als Tabelle mit ':' als Trennzeichen
dos2unix Export.csv
vim Export.csv
%s/:/;/g
Command-Line-Mode (analog ex)
C-a :
resize -v + 20
Vertikal plus 20 Zeilen
resize =
Gleiche Groesse aller Teilfenster
Detach/Reattach
===============
ssh heinz@nas
screen
Ctrl-A Ctrl-d (oder einfach nur 'd')
screen -r(esume)
Wurden mehrere Sitzungen detached praesentiert
screen -r
eine Auswahl
screen -R -D (screen -RD)
Reattach or create session
screen
screen -r (reattach)
Wichtig: Nach Split in neue Region wechseln (C-a <TAB>) und dort neue Shell kreieren (C-a c) oder zuweisen (C-a 1)
Wichtigste Befehle
C-a gefolgt von
: => Command-Line-Mode
title Fenstertitel vergeben
A Fenstertitel vergeben
c (create new window and shell)
Q (Nur aktuelles Fenster (jedoch alle Shells) behalten) z.B. um Split-Windows zu schliessen
S (horizontaler Split)
| (vertikaler Split)
" Fensterliste
<blank> naechste Sitzung/Shell
n naechste Sitzung/Shell
N zeige Nummer der Sitzung/Shell
d detach
0-9 Sitzung mit Nummer
C-\ Alle Sitzungen und screen beenden
? Hilfebildschirm
<TAB> naechste Region (bei Split)
Unterscheidung
Windows
Panes (Unterteilungen ein und desselben Fensters)
Befehle/Optionen
oft mit Folge-Option -t (== target)
Clients
tmux list-clients
Sessions
tmux ls Liste Sessions
tmux list-sessions Liste Sessions
tmux new-session -s "default"
tmux kill-session -t myname
Ctrl-b d detach
tmux a attach
tmux new -s myname Neue Session "myname"
tmux a -t myname (re)attach session "myname"
Ctrl-b s Liste Sessions
Windows
Ctrl-b c Neues Fenster
Ctrl-b n Wechsel zu naechstem Fenster
Ctrl-b p Wechsel zu vorherigem Fenster
Ctrl-b 0-9 Wechsel zu Fenster 0-9
Ctrl-b w Anzeige aller Fenster (analog Ctrl-A " bei screen)
Ctrl-b & kill window
Ctrl-b , name window
Panes
Ctrl-b " Split horizontal
Ctrl-b % Split vertikal
Ctrl-b x Kill pane
Ctrl-b <Pfeil> Pane wechseln
auch schnelle Kombination von Pfeilen nach Ctrl-b moeglich
Ctrl-b q Anzeige der Pane-Nummern
Folgeeingabe der Nummer waehrend Anzeige wechselt zu diesem Panel
Ctrl-b o Pane-Wechsel
Ctrl-b Ctrl-o Pane-Rotation
Ctrl-b z Toggle Pane-Fullscreen
Ctrl-b Alt 1-5 Pane-Anordnung nach Voreinstellung 1-5
Ctrl-b Alt 1 Nebeneinander mit GLEICHER Breite
Ctrl-b Alt 2 Untereinander mit GLEICHER Hoehe
Cave: 5 == tiled
Ctrl-b Ctrl <Pfeil> Pane-Größe in 1er-Schritten ändern
Ctrl-b Alt <Pfeil> Pane-Größe in 5er-Schritten ändern
Ctrl-b {} Pane-Swap (previous|next)
Command-Mode
Ctrl-b : Enter command-mode
: split-window -h untereinander
: split-window -v nebeneinander
: resize-pane -L|R|D|U 20 20 Zellen in angegeben Richtung vergroessern/verkleinern
In .tmux.conf anlegen, um letzten Pfadbestandteil in Statusleiste anzuzeigen
set-option -g status-interval 15
(Cave: status-interval ist das Update-Intervall in Sekunden)
set-option -g automatic-rename on
set-option -g automatic-rename-format '#{pane_current_path}'
cf. man tmux
b: => basename
set-option -g automatic-rename-format '#{b:pane_current_path}'
d: => dirname
set-option -g automatic-rename-format '#{d:pane_current_path}'
set -g display-panes-time 4000
Millisekunden, ueber welche die Pane-Nummern mit
Ctrl-b q
angezeigt werden und einen Wechsel durch Folgeeingabe der
Nummer erlauben
sed -i.bak -e '5,10d;12d' file # Zeile 5 bis 10 und Zeile 12 loeschen; Backup-File anlegen
--------------------------------------------------------------------------------------------------------------------
Option -E ermoeglicht extended regular expressions, d.h. keine Escape-\ vor z.B. Klammern
sed -E '
s/([0-9])\.([0-9])/\1\2/g # Tausendertrenner entfernen
' Eingabe.csv > Ausgabe.csv
--------------------------------------------------------------------------------------------------------------------
# Zeile mit 'Lachs' wird geaendert zu 'Forelle ...'
food=Lachs
sed -i '
/'${food}'/{
cForelle schmeckt besser
}
' "$log"
checkReturn "sed-Fehler"
--------------------------------------------------------------------------------------------------------------------
sed -n /anfang/,+3{ # Cave: +3 und ~3 (naechstes Vielfaches von 3) erlaubt, -3 nicht
p
}
sed '{
/sed /{
i\
}
}' Howto.txt > out
--------------------------------------------------------------------------------------------------------------------
sed -i -e '/verrechnet/!{ # Nur Zeilen ohne "verrechnet"-Vermerk
/^'${dateOfBooking}';'${value}'/{ # Potentieller Match
x # Tausch: Pattern-Space <-> Hold-Space
/verrechnet/{ # War "verrechnet" in Hold-Space ?
x # Pattern-Space wiederherstellen
b # Keine weiteren Kommandos anwenden und Zeile ausgeben
}
/verrechnet/!{ # Kein "verrechnet" in Hold-Space gewesen ?
x # Pattern-Sapce wiederherstellen
s/^\('${reverseDateOfBooking}';'${value}'.*\)/\1 verrechnet/ # "verrechnet anhaengen"
h # Zeile mit Verrechnungsvermerk in Hold-Space kopieren
}
}
}' $commentFile
--------------------------------------------------------------------------------------------------------------------
sed -i -n -e '1,/;"*'$paenultSaldo'"*$/ { # Von erster Zeile bis Zeile mit Eintrag $paenultSaldo
/;"*'$paenultSaldo'"*$/d # letzte Zeile loeschen
p # andere Zeilen ausgeben
}' $ultima
--------------------------------------------------------------------------------------------------------------------
sed -i -n -e '/^'${yearOfInterest}'/p' -e '/^Datum/p' "${resultFile}"
--------------------------------------------------------------------------------------------------------------------
sed -i ${lineNum}'s/!'${table}'!/!'${table}${count}'!/' "${file}"
--------------------------------------------------------------------------------------------------------------------
sed -n '
/BEGIN:VEVENT/,/END:VEVENT/{
/DTSTART/{
s/DTSTART;VALUE=DATE://
s/DTSTART://
s/DTSTART;TZID=Europe\/Berlin://
s/"//g
s/\\//g
h # Hold-Space
}
/DESCRIPTION/{
s/DESCRIPTION:\(.*\)/(\1)/
H # Netto-Beschreibung geklammert an Hold-Space anhaengen
}
/SUMMARY/{
s/SUMMARY://
s/"//g
s/\\//g
H # an Hold-Space anhaengen
g # Hold-Space => Pattern-Space
s/\(.*\)\n\((.*)\)\n\(.*\)/\1: \3 \2/ # Reihenfolge der durch Newline getrennten 3 Teile andern: Datum/Zeit\n(Kommentar)\nTitel => Datum/Zeit: Titel (Kommentar)
s/()// # Leere Kommentare loeschen
p
}
}
' "$icsFile" > "$patternFile"
--------------------------------------------------------------------------------------------------------------------
sed -i -e '/<d19/{
/<\/d19/!{
N
s/\n/ /g
}
}' $rawXml
checkReturn sed
--------------------------------------------------------------------------------------------------------------------
sed -i \
's///g # alle von Griechisch-Lexer stets belassenen entfernen
s/ä/\ä/g
s/ö/\ö/g
s/ü/\ü/g
s/Ä/\Ä/g
s/Ö/\Ö/g
s/Ü/\Ü/g
s/ß/\ß/g
s/(em\([[:alpha:]]\+\)[[:space:]]\+\([^)]\+\))/<em class="\1">\2<\/em>/g
s/(li[[:space:]]\+\([^)]\+\))/<li>\1<\/li>/g
s/(img[[:space:]]\+\([^)]\+\))/<img src="\1" width="10%" height="10%" alt=""\/>/g
s/(imgb[[:space:]]\+\([^)]\+\))/<img src="\1" width="10%" height="10%" alt="" border="1"\/>/g
s/
/<br\/><br\/>/g
s/
/<br\/>/g' "$file"
--------------------------------------------------------------------------------------------------------------------
sed -n '/Filter.*stream/,/^endstream/ {
/Filter.*stream/d
/^endstream/d
p
}' "$qualInFile" > "$qualOutFile"
--------------------------------------------------------------------------------------------------------------------
sed -n -e '/<Placemark>/,/<\/Placemark>/{ # Innerhalb eines Placemark-Tags
#------------------------------------------------
# Bei gefundenem Pfad Pfad-Marker setzen und
# Anfang eines Placemark-Tags ausgeben
#------------------------------------------------
/Path/{ # "Path" vorhanden ?
s/.*/Pfad_gefunden/ # Pfad-Marker erzeugen
h # Pfad-Marker => hold space
#------------------------------------------------
# Anfang eines Placemark-Tags ausgeben
#------------------------------------------------
i\
<Placemark>\
<name>$name</name>\
<styleUrl>#lineStyle</styleUrl>\
<Style>\
<LineStyle>\
<color>ff0000ff</color>\
<width>5</width>\
<scale>5</scale>\
</LineStyle>\
</Style>\
<LineString>\
<tessellate>1</tessellate>\
<coordinates>
}
#---------------------------------------------------
# Bei Ende eines Placemarks mit Pfad Pfad-Marker in hold space loeschen
# und Placemark-Tag in der Ausgabe abschliessen
#---------------------------------------------------
/<\/Placemark>/{ # Placemark-Ende
g
/Pfad_gefunden/{ # Pfad-Marker vorhanden ?
s/.*// # Leerstring erzeugen
h # => Pfad-Marker in hold space loeschen
#------------------------------------------------
# Ende eines Placemark-Tags ausgeben
#------------------------------------------------
i\
</coordinates>\
</LineString>\
</Placemark>
}
}
#---------------------------------------------------
# Zahlentupel
# 6.451126,51.664082,22.18
#---------------------------------------------------
/^[[:digit:]\., ]*$/{ # Falls Zahlentupel
G # hold space mit Newline anhaengen
/Pfad_gefunden/{ # Pfad-Marker vorhanden ?
P # Zahlen (bis Newline) ausgeben
}
}
}' "$infile" >> $outfile
--------------------------------------------------------------------------------------------------------------------
sed -n -e '/EXTINF/{
#----------------------------------------------
# Angaben vor Sendernamen loeschen,
# Leerzeichen aus letzterem entfernen,
# Umlaute ersetzen,
# Sendername gross schreiben
#----------------------------------------------
s/#EXTINF:[,0-9 ]\+//
s/ /_/g
s/Ä/Ae/g
s/Ö/Oe/g
s/Ü/Ue/g
s/ä/ae/g
s/ö/oe/g
s/ü/ue/g
s/.*/\U&/
#----------------------------------------------
# Streaming-URL in naechster Zeile lesen
#----------------------------------------------
N
#----------------------------------------------
# Zeilen Verketten
#----------------------------------------------
s/\n/:/
#----------------------------------------------
# Verkettetung ausgeben
#----------------------------------------------
p
}' "$file"
--------------------------------------------------------------------------------------------------------------------
sed -n \
-e '/^\(leftstring\|rightstring\|label\|let\)/ {
#------------------------------------------------------------------------------
# Ersetzung aller Zellenbezeichner mit 1-stelliger Zeile:
# rightstring AC1 = "Hugo ist lieb"
# =>
# rightstring 001AC = "Hugo ist lieb"
#------------------------------------------------------------------------------
s/^[[:alpha:]]\+ \+\([[:alpha:]]\+\)\([[:digit:]]\{1\}\) /00\2\1 /
#------------------------------------------------------------------------------
# Ersetzung aller Zellenbezeichner mit 2-stelliger Zeile:
# let Q23 = 0.544*$B$7
# =>
# let 023Q = 0.544*$B$7
#------------------------------------------------------------------------------
s/^[[:alpha:]]\+ \+\([[:alpha:]]\+\)\([[:digit:]]\{2\}\) /0\2\1 /
#------------------------------------------------------------------------------
# sc-Funktionen => ODF-Funktionen, bitte ergaenzen
#------------------------------------------------------------------------------
s/@sum/summe/g
#------------------------------------------------------------------------------
# Dezimalpunkt => Dezimalkomma
#------------------------------------------------------------------------------
s/\([[:digit:]]\)\.\([[:digit:]]\)/\1,\2/g
#------------------------------------------------------------------------------
# Einfuegen des "Internal Field Separators": " = " => "|"
#------------------------------------------------------------------------------
s/ \+= \+/|/
#------------------------------------------------------------------------------
# Vor Rechenausdruecken, also nicht nur einer einzigen (!) Zahl, fuehrendes "="
# fuer ODF-Formeln einfuegen
#------------------------------------------------------------------------------
# Falls kein String, also kein Textfeld, damit also Zahl oder Rechenausdruck
#------------------------------------------------------------------------------
/["]/! {
#----------------------------------------------------------------------------
# Falls rechts von "|" bis Zeilenende nicht nur eine einzige Zahl mit optionalem Dezimaltrenner
#----------------------------------------------------------------------------
/|[[:digit:]]\+,\{0,1\}[[:digit:]]\+$/! {
#--------------------------------------------------------------------------
# fuehrendes '=' fuer Formelerkennung in ODF einfuegen
#--------------------------------------------------------------------------
s/|/|=/
}
}
p
}' $infile | sort > $tmpfile
--------------------------------------------------------------------------------------------------------------------
sed -e '/^-/d' \
-e '/ *\(Summe\|Datum\|Soll\)/d' \
"$account" | sort -b -t '|' -k 3 > "$out"
--------------------------------------------------------------------------------------------------------------------
sed -i -n '/^\('${chapters//,/\\|}'\);/p' "$randomFile"
--------------------------------------------------------------------------------------------------------------------
done < <(sed -n "$startLine,${endLine}p" "$infile")
--------------------------------------------------------------------------------------------------------------------
sed '/^<synonym>/{
s/ᾰ́\|ā\|ά\|ᾱ\|ἄ\|ά\|ὰ\|α\|ἀ\|ἁ\|ἂ\|ἃ\|ἅ\|ἆ\|ἇ\|Α\|Ἀ\|Ἁ\|Ἂ\|Ἃ\|Ἄ\|Ἅ\|Ἆ\|Ἇ\|ᾲ\|ᾳ\|ᾴ\|ᾶ\|ᾷ\|Ὰ\|Ά\|ᾼ/a/g
s/β\|Β/b/g
s/γ\|Γ/g/g
s/δ\|Δ/d/g
s/έ\|ἔ\|έ\|ὲ\|ε\|ἐ\|ἑ\|ἒ\|ἓ\|ἕ\|Ε\|Ἐ\|Ἑ\|Ἒ\|Ἓ\|Ἔ\|Ἕ\|Ὲ\|Έ/e/g
s/ζ\|Ζ/z/g
s/h̃\|ή\|ἤ\|ἥ\|ή\|ὴ\|η\|ἠ\|ἡ\|ἢ\|ἣ\|ἥ\|ἦ\|ἧ\|Η\|Ἠ\|Ἡ\|Ἢ\|Ἣ\|Ἤ\|Ἥ\|Ἦ\|Ἧ\|ῂ\|ῃ\|ῄ\|ῆ\|ῇ\|Ὴ\|Ή\|ῌ/h/g
s/θ\|Θ/q/g
s/ΐ\|ῑ\|ĩ\|ί\|ί\|ὶ\|ι\|ἰ\|ἱ\|ἲ\|ἳ\|ἵ\|ἶ\|ἷ\|ἴ\|Ι\|Ἰ\|Ἱ\|Ἲ\|Ἳ\|Ἴ\|Ἵ\|Ἶ\|Ἷ\|ῖ\|Ὶ\|Ί/i/g
s/κ\|Κ/k/g
s/λ\|Λ/l/g
s/μ\|Μ/m/g
s/ν\|Ν/n/g
s/ξ\|Ξ/c/g
s/ό\|ὄ\|ό\|ὸ\|ο\|ὀ\|ὁ\|ὂ\|ὃ\|ὅ\|Ο\|Ὀ\|Ὁ\|Ὂ\|Ὃ\|Ὄ\|Ὅ\|Ὸ\|Ό/o/g
s/π\|Π/p/g
s/r\|ρ\|ῥ\|Ρ\|Ῥ/r/g
s/σ\|ς\|Σ/s/g
s/τ\|Τ/t/g
s/ύ\|υ\|ὔ\|ύ\|ὺ\|ὐ\|ὑ\|ὒ\|ὓ\|ὕ\|ὖ\|ὗ\|Y\|Ὑ\|Ὓ\|Ὕ\|Ὗ\|ῦ\|Ὺ\|Ύ/u/g
s/φ\|Φ/f/g
s/χ\|Χ/x/g
s/ψ\|Ψ/y/g
s/w̃\|ώ\|ὤ\|ᾠ\|ώ\|ὼ\|ω\|ὠ\|ὡ\|ὢ\|ὣ\|ὥ\|ὦ\|ὧ\|Ω\|Ὠ\|Ὡ\|Ὢ\|Ὣ\|Ὤ\|Ὥ\|Ὦ\|Ὧ\|ῲ\|ῳ\|ῴ\|ῶ\|ῷ\|Ὼ\|Ώ\|ῼ/w/g
s/>[^a-z]/>/
}' "$tmpFile" > "$outFile"
--------------------------------------------------------------------------------------------------------------------
sed '
s/<img[^>]*>//g # nervige Images entfernen
s/nowrap=""//g # stoerende Attribute entfernen
s:</tr>:</tr>\n:g # Zeilenumbrueche nach Tabellenzeilen
' "$container" > "$containerTmp"
--------------------------------------------------------------------------------------------------------------------
sed '
/Genehmigung steht aus/{
N # Naechste Zeile einlesen und
s/\n// # Zeilenumbruch dazwischen loeschen
}
' "$file" > "$tmp"
--------------------------------------------------------------------------------------------------------------------
sed '
/placeholder_0/{
s//'"$time"'/
}
/placeholder_1/{
r '$report'
d # darf erst NACH read stehen
}
' "$websiteTemplate" > "$website"
--------------------------------------------------------------------------------------------------------------------
sed -n '
/<Beschreibung>/,/<\/Beschreibung>/{
/<Beschreibung>/d
/<\/Beschreibung>/d
s/^[[:space:]]*#//
p
}
' "$file" >> "$outfile"
--------------------------------------------------------------------------------------------------------------------
sed '
/placeholder_0/{
r '$citation'
d # darf erst NACH read stehen
}
/placeholder_1/{
s//'"$time"'/
}
/placeholder_2/{
r '$websiteConfig'
d # darf erst NACH read stehen
}
' "$websiteTemplate" > "$website"
--------------------------------------------------------------------------------------------------------------------
sed '/^[[:space:];]*$/{
d # Quasi-Leerzeilen loeschen
}
/AZDEPA/d # Vertragszeile loeschen
/^[[:space:]]*Date/{
s/^/#/ # Header-Zeile kommentieren
}
s/[^[:space:]]\+greifend/uebergreifend/g # verungluecktes erstes Zeichen bei ..bergreifend korrigieren
#----------------------------------------------------------------------------------------------
# Namenskorrekturen
#----------------------------------------------------------------------------------------------
s/D.niel/Daniel/g
/Kuelheim/{
s/Ren./Rene/
}
/Fink/{
s/Marko/Marco/
}
#----------------------------------------------------------------------------------------------
s/[[:space:]]\+€[[:space:]]\+//g # Euro-Zeichen mit Leerzeichen loeschen
s/[[:space:]]\+;/;/g # Leerzeichen loeschen
s/;[[:space:]]\+/;/g # Leerzeichen loeschen
s/ä/ae/g
s/ü/ue/g
s/ö/oe/g
s/Ä/Ae/g
s/Ü/Ue/g
s/Ö/Oe/g
s/ß/ss/g
s/[[:space:]]*Dr\.[[:space:]]*// # Akad. Titel loeschen
' "$infile" > "$infileTmp"
--------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------
# Nur Zeilen mit Datum oder "dispatched" beibehalten
#-------------------------------------------------------------------------------------------
sed -n '{
/\(^ *[0-9]\{4\}\|dispatched\)/{ # Nur Zeilen mit Datum zu Beginn oder "dispatched" beibehalten
s/^ *// # Initialen Whitespace loeschen
s/\([0-9]\{4\}\)[- ]\([0-9]\{2\}\)[- ][0-9]\{2\}/\1\2/ # 2023-01-04 oder 2023 01 04 => 202301 von Datum nur Jahr und Monat beibehalten (auch bei fehlerhaften Eintragen ohne Bindestrich)
s/\./,/g # Dezimaltrenner bereinigen (Cave: lazy-Variante: nicht geprueft wird, ob Punkt zwischen 2 Zahlen steht)
s/ \+PRO/ PRO/ # Einzelnes Blank vor Projektnummer verdoppeln (fuer spaetere Strichpunktersetzung)
/\(pending\|disabled\)/Id # Status-Ausschluesse
s/groeger/Groeger/I
s/troeger/Troeger/I
s/ARNO/Arno/
s/ \{2,\}/;/g # Blankfolgen >= 2 durch ; ersetzen (funktioniert wegen "greedy")
p # Ausgabe
}
}' "$out1" > "$out2"
sed -i -n '
$!{ # Fuer alle Zeilen bis auf die letzte
h # Zwischenspeichern
n # Folgezeile einlesen
/dispatched/{ # "dispatched"-Zeile ?
g # Holdspace => Patternspace
s/$/;dispatched/ # "dispatched" mit ";" anhaengen
p # Ausgabe
}
/dispatched/!{ # Nein, Datumszeile
x # Patternspace <=> Holdspace
s/$/;/ # ";" anfuegen
p # Ausgabe
g # Patternspace => Holdspace
s/$/;/ # ";" anfuegen
p
}
}
${
s/$/;/ # ";" anfuegen und
p # ausgeben
}
' "$out2"
awk [ -F separator -FS=regex ] [ -v var=value ... ] [ -f prog ... ]
awk -F '\t' '{ ... }' files
awk -FS="[\t\n]" ...
awk '{ ... }' var=willi *.tex var=heinz *.tex # 2 Durchlaeufe mit verschiedenen Initialisierungen VOR Verarbeitung jeweiliger Eingabedatei, aber NACH BEGIN-Abschnitt
awk '{ print $n }' n=4 Datei_1 n=2 Datei_2
... -v var=heinz # Variable wird VOR BEGIN-Abschnitt initialisiert
Modell
======
pattern { action }
pattern # Default-Aktion: print
{ action } # Aktion ohne Bedingung == fuer jede Zeile
BEGIN und END # Special patterns
str1="hugo";
str2="willi";
str=str1 str2 # Es gibt keinen speziellen Konkatenierungsoperator
a=(var1>var2) ? x^3 : x^4
$0 ~ /\.[ch]$/
/\.[ch]$/ # synonym ($0 ist Default-String)
$4 !~ /\.+,\.+/
-------------------------------------------------------
BEGIN {IGNORECASE=1} # Cave: Gilt global, nicht nur fuer 1 Vergleich
string=ABC
($0 ~ /a/) # case-insensitive-match
-------------------------------------------------------
NF == 0 # Leerzeile
NF > 3 # Anzahl Felder
NR < 5 # Zeilennummer
if((col+0) > NF) # Cave: Zwangskonvertierung String => Zahl
NR == 3 && FILENAME ~ /[0-9][a-z]/
NR == 2,NR == 9 # Fuer Zeilen 2-9
$1 == "Hugo" { print $2; }
/Hugo/ || /Willi/ { ... }
! /Franz/ { ... }
/<hugo>/,/<\/hugo>/ # Innerhalb Tag
$1 == "on",$1 == "off" { ... }
echo "Heinz Willi Franz" | awk '{ print $3 $2 $1}' # Nicht-Komma-separierte Elemente werden in awk konkateniert => FranzWilliHeinz
echo "Heinz Willi Franz" | awk '{ print $3,$2,$1}' # ',' bewirkt Einfuegen des Default OFS (' ') => Franz Willi Heinz
awk '{ OFS="..."; print $1, $2 } # Output-Field-Separator
awk '{ sum += length($0) } END { print "Summe: " sum }' # Garantierte Default-Initialiserung jeder Variable macht sum=0 unnoetig
awk '{ print $1, log($1) }'
awk -v column=5 '{ sum+=$column } END { print sum/NR }'
awk '{ sum+=$NF; print $NF, sum } # laufende Summe der letzten Spalte
awk '/pattern|pattern/ { print FILENAME ": " NR " : " $0}' files # egrep-Ersatz
awk 'BEGIN { FS=OFS="\t" } { print $3, $2 }' infile > outfile
awk 'BEGIN { ORS="\n\n" } { print }' files # Leerzeilen einfuegen
awk 'BEGIN { ORS =" "; RS="<[^<>]*>" } { print }' *.html # Fortgeschritten: HTML-Tags werden zu record-separators, in Ausgabe durch ' ' ersetzt und damit praktisch entfernt
for (key in assocArr){
if(assocArr[name] == var){
break
}
}
#---------------------------------------------------
#!/usr/bin/awk -f # Shebang erfordert -f-Option
{
print "Na also " $0;
}
#---------------------------------------------------
PROCINFO["sorted_in"] = "@ind_str_asc"; # Sortierung
#---------------------------------------------------
delete array[key]
if !(key in assocArr) ... # richtig
if(assocArr[key] != "") # falsch, da hierbei assocArr[key] (leer) angelegt wird
if ((key1,key2,key3) in tripleAssocArr) # Elementpruefung bei 3-dimensionalem Hash
#---------------------------------------------------
getline
=======
getline var < file
while((getline words[nWords++] < file) > 0){
...
}
#---------------------------------------------------
# Zuweisung einer Feld-Variable (hier auf sich selbst)
# ersetzt FS durch OFS in aktuellem record
#---------------------------------------------------
awk 'BEGIN{OFS=":"} {$1=$1; print}' < file # a b c d => a:b:c:d # print gibt record OFS-getrennt aus
#---------------------------------------------------
cmd | getline
"date" | getline now # command wird in '"' eingeschlossen !
close("date")
command="head -n 15 /etc/hosts"
while((command | getline line) > 0){
}
close(command)
#---------------------------------------------------
tmp=/tmpfile
command="sort -n > " tmp # Cave: Konkatenation 2er Strings
for (key in assocArr){
print key ": " assocArr[key] | command
}
close(command)
#---------------------------------------------------
tmp=/tmpfile
for (key in assocArr){
print "name: " assocArr[key] > tmp
}
close(tmp)
system("sort < " tmp) # Cave: String-Konkatenation, Cave: Jeder Aufruf von system(...) startet neue shell
#---------------------------------------------------
system("cat <<EOF\neins\nzwei\ndreiEOF")
#---------------------------------------------------
myfunc(arg1,arg2, result){ # Lokale Variable result wird in Deklaration deklariert und (Konvention) durch Whitespace getrennt
result =arg1 " " arg2
return result
}
myfunc("Hugo","Willi")
#---------------------------------------------------
monthString="Jan Feb Maer Apr Mai Jun Jul Aug Sep Okt Nov Dez";
split(monthString,months); # Cave: Split liefert einen mit Index 1 beginnenden Array
printf(Monat: %s\n",months[5]);
#---------------------------------------------------
match("foobar",/(f+).*(b+)/,matchArr)
printf("Alles: %s\n",matchArr[0]);
printf("Erste Klammer: %s\n",matchArr[1]);
printf("Zweite Klammer: %s\n",matchArr[1]);
#---------------------------------------------------
Funktionen
==========
passing convention:
values are passed by value
arrays are passed by reference
myfunc(i, j) # Konvention: lokale Variablen nach Argumenten durch White-Space getrennt (j ist lokal, aber uebergeben werden darf nur i)
substr(string,start,len)
toupper(string)
tolower(string)
index(string,pattern)
match(string,regex)
alternativ: string ~ regex
sub(regex,replacement,string)
gsub(regex,replacement,string) # Default-string ist $0
Cave: '&' in replacement fuegt match ein
gsub([aeiou],"&&") # verdoppelt gefundene Vokale der aktuellen Zeile
result=gensub(regex,replacement,howto,string) # Cave: Rueckgabe des Ergebnisses UND Faehigkeit zu back-references
resource=gensub(/([[:alpha:]]+)[[:space:]]*,[[:space:]]*([[:alpha:]]+)/, "\\2_\\1", "g", resource); # Cave: "g" == global .... 1 waere 1.Treffer ... 3 waere 3. Treffer
Synonym sind
============
phone=gensub(/([0-9]) +([0-9])/,"\\1\\2","g",phone); # Leerzeichen zwischen Zahlen ersetzen
gsub(/ +/,"",phone); # Cave: gensub liefert ersetzten string, gsub die Anzahl Ersetzungen zurueck und aendert string direkt
split(string,array,regex) # Default-regex ist Wert von FS (field-separator) => Rueckgabe der Array-Laenge (Cave: array start mit Index 1)
split(string,array,"") # Split jedes Zeichens
split("",array) # Effizientes Loeschen von array
#---------------------------------------------------
# date and time
#---------------------------------------------------
now=systime(); # number of seconds (epoch)
then=mktime("2023 12 31 23 00 00")
printf("%s <=> %s\n",strftime("%F",now),strftime("%F",then)); # %F analogous to 'date'-Format-String => "%Y-%m-%d"
year=2022;
month=06;
day1=13;
day2=27;
secsPerDay=3600.0*24.0;
startString=year " " month " " day1 " 03 00 00";
startTime=mktime(startString);
endString=year " " month " " day2 " 03 00 00";
endTime=mktime(endString);
days=sprintf("%d",((endTime-startTime)/secsPerDay)+1);
.config/mc/mc.ext
(Shift) F5 # Copy
(Shift) F6 # Move
F7 # Verzeichnis anlegen
F8 # Delete
F10 # Beenden
F4 # vim
F3 # Viewer
Ctrl-i/TAB # Panel wechseln
Alt-, # Toggle Left/Right - Top/Bottom-Ansicht
Alt-t # Cycle Listing-Modes
Ctrl-t/Insert # Objekte selektieren/deselektieren
Ctrl-u # Panels tauschen
Ctrl-PgUp # Vaterverzeichnis
# oder in /etc/mc/mc.default.keymap festlegen (Raspberry)
Alt-. # Toggle hidden files
Alt-i # Verzeichnis in Nachbar-Panel laden
Alt-o # Inhalt des Verzeichnisses in anderem Panel laden
Alt-c # Quick-cd
Beispiel: sftp://heinz@adlatus
Alt-H # Chronik
Alt-y # vorheriges Verzeichnis in Historie
Alt-u # naechstes Verzeichnis in Historie
Alt-? # Datei suchen analog 'find'
Alt-g # Oberste, mittlere, unterste _sichtbare_ Datei auswaehlen
-r
-j
Alt-v/Ctrl-v PgUp/PgDown # Eine Seite nach unten/oben
Alt-</> HOME/END # zu erster/letzter Datei springen
Alt-s <Anfangsbuchstaben> # Springe zu Datei nach Muster ... (Wildcards * ?)
mehrfach => naechster Treffer
Ctrl-\ # Directory Hotlist (funktioniert nicht unter Windows (cygwin/wsl))
Ctrl-o # Toggle shell
Ctrl-space # Verzeichnisgroesse ermitteln (Anzeige im Panel)
Ctrl-x (s|v|l) # Symbolische Links oder harten Link im anderen Verzeichnis anlegen
-s: absoluter Pfad
-v: relativer Pfad
Ctrl-x c # chmod-Dialog
Ctrl-x d # Verzeichnisse vergleichen
Ctrl-x i # Toggle info der aktuellen Datei in anderem Panel
Ctrl-x o # chown-Dialog
Ctrl-x t # Markierte Datei => Kommandozeile
Ctrl-x q # Toggle Quick-View der aktuellen Datei in anderem Panel
(Alt|Ctrl)-Enter # Selektierte Datei => Shell
Shift-(Alt|Ctrl)-Enter # Selektierte voll qualifizierte Datei => Shell
+ # Dateien selektieren nach Muster
-|\ # Dateien nach Muster deselektieren
* # Auswahl umkehren (nur Dateien)
cd .tgz *.tar.gz
F2 # User-Menu: Popup-Auswahl der Aktionen fuer markierte Dateien
# Hier koennen eigene Quasi-Makros hinzugefuegt werden
# F9 => Command => Edit Menu File => User
# z.B. eine Option 8 hinzufuegen
@ # Kommando auf selektierter Datei ausfuehren
# Beispiel: F2 @ (mit Folgeeingabe) zip hugo.zip
# Cave: Archive werden in Vaterverzeichnis abgelegt
SSH/SFTP
F9 R
SFTP
Achtung: .ssh/config wird ignoriert
Shell-Link/-Verbindung
.ssh/config funktioniert
z.B.
heinz@adlatus/home/heinz
heinz@home_avc/home/heinz/daten
cd sftp://heinz@strato
cd sh://heinz@strato
Ruecksprung: cd
Command-Line
z.B. cd ...
ESC-Tab => autocompletion
mehrfach => Auswahl
F9 => Options => Configuration
ESC-Tastenmodus => Einzelner Tastendruck
F9 => Options => Layout
Kommando-Prompt enthaken
=> Dateisuche nun ohne
Alt-s <letter(s)>
moeglich
F9 => Options => Panel Options => Quick Search
Case-insensitive einstellen
F9 => Options => Configuration
User internal edit/view abhaken
=> System-Editor wird verwendet
F9 => Command => Edit Extension Files
== Editieren der mc-config-Datei
Aufrufvarianten via ssh
=======================
Variante 1
==========
Aufruf rsync-Daemon auf Zielrechner ueber bestehende ssh-Verbindung mit Portweiterleitung
Server
======
Konfiguration des rsync-Daemon mit
- Passwort-Datei
- Berechtigungsangaben
in /etc/rsyncd.conf
[Backup_WSL]
comment = Backup_ID-Rechner
path = /home/heinz/daten/Heinz/Backup/Allianz_VM/Backup_WSL
read only = no
list = yes
uid = heinz
gid = users
auth users = heinz
secrets file = /etc/rsyncd.secrets
Start des rsync-daemon mit
rsync --daemon
Client
======
Expliziter Vorab-Aufbau einer ssh-Verbindung mit Portweiterleitung in .ssh/config
LocalForward 30400 127.0.0.1:873
Aufruf des rsync-Daemon auf Zielrechner mit URL-Syntax und '/' (vermutlich alternativ '::'), gefolgt von Name des Eintrages in rsyncd.conf
rsync <options> <source> heinz@localhost:30400/Backup_WSL
/\
||
slash
Variante 2
==========
Ad-Hoc-Aufbau einer ssh-Verbindung ohne Portweiterleitung und ohne rsync-Daemon(-Einrichtung) auf Zielserver
ssh-Verbindung wurde vorher in .ssh/config konfiguriert
Host home
Hostname www2.breinlinger.org
Port 22
IdentityFile ~/.ssh/home/id_rsa_%r
ProxyCommand nc -X 5 -x svr001-e1-socks.zone2.proxy.allianz:1080 %h %p
LocalForward 30400 127.0.0.1:873 # rsync-Daemon fuer Variante 1 oben, hier NICHT noetig
RemoteForward 10200 127.0.0.1:23 # ssh
rsync <options> <source> heinz@home:daten/Heinz/Backup/Allianz_VM/Backup_WSL
/\
||
colon
cf. Abschnitte
INCLUDE/EXCLUDE PATTERN RULES
ANCHORING INCLUDE/EXCLUDE PATTERNS
in man-Page
Wenn Dateien nur aufgrund abweichender Groesse uebertragen werden sollen:
rsync -rzv(n) --size-only dir/* dir2/
Grundregeln
===========
Pfade sind alle rekursiv ab root qualifizierten Verzeichnisse
Pattern werden rekursiv ueber alle so qualifizierten Pfade ab root matched
/source
/source/afile
/source/adir
/source/adir/bdir
/source/adir/bdir/cfile
Jeder Match wird von links nach rechts auf den gesamten aktuellen Pfad angewandt
include-Matches kompensieren exclude-Matches nur genau auf derselben Ebene
== Verhalten von unison
da auf jeder Ebene ueber Aus-/Einschluesse enschieden wird, kommen unterhalb eines
Ausschluesses gelegene Einschluesse nicht mehr zum Zuge
excludeFile
*/ => Ausschluss aller Verzeichnisse
includeFile
/subdir/hugo.java => wird nicht mehr angewandt, da subdir bereits ausgeschlossen wurde
-a impliziert recursive traversal
Trailing '/' oder nicht hat nur bei Quellverzeichnis Bedeutung
rsync -a /source /target[/]
Uebertraegt source
rsync -a /source/ /target[/]
Uebertraegt Inhalte von source
Root ist immer das vor dem letzten '/' beschnittene Quellverzeichnis
rsync -a /a/b/c/d/ ..........
Root: /a/b/c/d
rsync -a /a/b/c/d ..........
Root: /a/b/c
* matched alles, stoppt jedoch bei '/', d.h. '/' wird mit-matched, DANACH jedoch gestoppt
=>
excludeFile:
* => schliesst alles aus, d.h. alle Verzeichnisse (mit trailing '/') und alle Dateien
includeFile:
*/ => schliesst alle Verzeichnisse ein
? matched genau ein Zeichen außer '/'
** matched alles inkl. '/'
dirname/*** matched wie zusammen
dirname
dirname/**
Muster mit fuehrendem '/' sind unterhalb Root verankert
Muster ohne fuehrenden '/' matchen ueberall
Muster mit '/' irgendwo (ausser am Ende) matchen den gesamten Pfad
sub/foo => matched ueberall im Pfad
Muster mit trailing '/' matchen nur Verzeichnisse (am Ende des Pfades)
*/ => matched jeweiliges Endverzeichnis des Pfades und damit rekursiv jeden denkbaren Pfad ab root
rsync --exclude='*/' -a . version_3
alle Dateien (jedoch kein Verzeichnis) in Unterverzeichnis version_3 archivieren
rsync -a /source/adir /target
excludeFile
/adir => matched nur /source/adir, nicht /source/bdir/cdir/adir
bdir/cdir => matched /source/adir/bdir/cdir
Strato_alt => Strato_neu:
=========================
.ssh/config
Host strato_neu
Hostname 87.106.235.227
IdentityFile ~/.ssh/strato/id_rsa_%r
LocalForward 4444 127.0.01:873
ssh root@strato_neu
rsync --archive --password-file=/etc/rsyncd.secrets /var/www/html/ rsync://root@localhost:4444/Web
Beispiel anhand des Klonens von Partitionen
===========================================
rsync --stats --progress --numeric-ids -axAhHSP /mnt/* /media/austausch
Cave: der '*' ist optional
Optionen
a: archive-mode == -rlptgoD
r: recursive
l: links als links kopieren
p: preserve permissions
t: preserve modification times
g: preserve group
o: preserve owner
D: == --devices (preserve device file (super-user only)) --specials (preserve special files)
x: only-one-filesystem (== exclude mounts darunter)
A: (preserve acls) kann entfallen
H: preserve hard-links
h: human-readable
S: intelligentes Kopieren von sparse-files
P: partial progress
Generell
========
Grundregel 1: Man muss aufpassen, sich mit ignore nicht ein Verzeichnis bereits auszuschliessen,
auf dessen spezielle Elemente (Verzeichnisse oder Dateien gleichermassen)
danach eine ignorenot-Regel angewandt werden soll
=> nicht moeglich ist daher, in einem Verzeichnisbaum nur alle *.java-Dateien oder alle src-Verzeichnisse zu sichern
Grundregel 2: Jedes Element wird auf ALLE Regeln zu matchen versucht, sofern ein vorheriges ignore dieses nicht
ausgeschlossen hat =>
Eine Anweisungsfolge
Path=.ssr
ignore=Name logs
anstelle
ignore=Path .ssr/logs
ist gefaehrlich, da die ignore-Anweisung auch auf ALLE anderen Pfad-Anweisungen angewandt wird
Wenn ein qualifiertes Element mit ignore ausgeschlossen wurde, kann ignorenot nicht auf
Unterelemente angewandt werden, d.h.
ignorenot Path=.ssr
verwirft .ssr und es gibt gar keine Elemente .ssr/* mehr, auf welche ein folgendes ignorenot-Muster
ignorenot Path=.ssr/*.content
angewandt werden koennte
Richtig folglich
ignore=Path .ssr/*
ignorenot=Path .ssr/hugo
.ssr wird nicht ausgeschlossen => naechste Elemente fuer den Algorithmus sind nun alle .ssr/* =>
.ssr/* werden ausgeschlossen, .ssr/hugo jedoch nicht
Daher funktioniert auch
Ignore=Regex .*\.class
matched den gesamten Pfad bis zu einem Verzeichnis oder einer Datei mit Endunge .class
und schliesst daher effektiv alle *.class-Dateien in allen Unterverzeichnissen aus
wohingegen das vermeintliche Positiv-Beispiel
Ignorenot=Regex .*\.java
nur auf Verzeichnisse und Dateien ueberhaupt angewandt wird, welche nicht zuvor durch ein
Ignore=Path ...
ausgeschlossen wurden
es funktioniert also nicht
Ignore=Path repository/* => schliesst alles direkt unter repository (bereits) aus, z.B. repository/subdir
IgnoreNot=Regex .*\.java => wuerde nur fuer repository/*.java (aus der ignorierten Teilmenge) funktionieren, da
alle respository/<unterverzeichnis> bereits ignoriert sind, wodurch z.B.
repository/subdir/hugo.java
als Match auf .*/.java gar nicht mehr ausgewertet wird
Synonym sind
IgnoreNot=Name *.ext
Ignoriert jedes Unterverzeichnis oder jede Datei, welche auf .ext enden (Achtung globbing: '/' wird durch * nicht matched, . matched '.')
Ignorenot=Regex .*/\.ext
Matched gesamten Pfad bis zu einem Verzeichnis/einer Datei mit Endung .ext
Es klappt zumindest angenaehert, d.h. bestmoeglich
path=A
#------------------------------------------------------------------------------------------------------------------------------------
# Globbing: Datei oder effektiv letztes Verzeichnis beginnend mit oder ohne '.', beliebiger Zeichenfolge, '.' und beliebiger Endung ausschliessen
#
# Cave: Annahme ist, dass es kein Verzeichnis, sondern nur Dateien mit einem '.' gibt
# Dateien ohne '.' werden leider ebenfalls gesichert, da der Ausschluss nur von Dateien (nicht Verzeichnissen) ohne '.' nicht moeglich ist
#------------------------------------------------------------------------------------------------------------------------------------
ignore=Name {,.}*.*
#------------------------------------------------------------------------------------------------------------------------------------
# Globbing: Dito, jedoch mit Endung java
#------------------------------------------------------------------------------------------------------------------------------------
ignorenot=Name {,.}*.java
Achtung
=======
Path, Name und PathBelow verwenden globbing
* matched beliebige Zeichenfolge außer '/' und zu Beginn ein '.'
? matched genau ein Zeichen außer '/' und zu Begin ein '.'
ausserdem:
[abc]
Zeichen a oder b oder c
und {xx,yy,zz}
Zeichenfolge xx oder yy oder zz
Regex verwendert Posix-Extended-Regular-Expression, d.h. .* matched alle Zeichen INKL. '/' und . matched ein beliebiges Zeichen
Anweisungen
===========
ignore (oder ignorenot)
Cave:
ignore=Regex ...
Posix-Extended-Regular-Expression
muss den gesamten Pfad matchen
\.
matched '.'
.*
matched alles, also auch '/'
Beispiel
ignore=Regex .*\.class
sichert alles in allen Unterverzeichnissen außer Verzeichnissen oder Dateien, welche auf .class enden, da .* auch '/' matched
ignore=(Path|PathBelow) ...
File-Globbing
* und ?
Cave: * matched NICHT '/'
BelowPath matched auf Path, zusaetzlich jedoch auch auf alles Darunterliegende
ignore=Name logs
jeder Unterverzeichnisbaum, dessen letztes Verzeichnis logs ist, oder jede Datei namens logs irgendwo im Baum wird ignoriert
Fuer den Ausschluss einer Dateiart ausser in einem bestimmten Unterverzeichnis
ignore=Name *.ext
Cave: Globbing
ignorenot=Regex .*/sollverzeichnis/*\.ext
Cave: Posix-Extended-Regular-Expression
Ruby-Snippets zu Win32OLE (WSH, Outlook, Excel, Word)
Windows-Scripting-Host
======================
wsh.AppActivate(pid)
wsh.SendKeys(key)
wsh=WIN32OLE.new('WScript.Shell'); checkValue(wsh)
wsh.run("cmd.exe /C start microsoft-edge:http://www.google.de");
#---------------------------------------------------------------
processArray=Array.new
taskList=%x(tasklist)
puts("----------------------")
taskList.split(/\n/).each { |task|
# if(task.match(/^#{processName}\S+\s+(\d+)/i))
if(task.match(/^#{processName}\s+(\d+)/i))
puts("Job: #{$1}")
processArray << $1
end
}
Win32OLE
========
Outlook
=======
#---------------------------------------------------------------
$outlook=WIN32OLE.new('Outlook.Application'); checkValue($outlook)
$outlook=WIN32OLE.connect('Outlook.Application')
WIN32OLE.const_load($outlook,OutlookConst)
$namespaceOutlook=$outlook.GetNamespace("MAPI")
$topFolder=$namespaceOutlook.Folders.Item('heinz.breinlinger@allianz.de')
sender.gsub!(/dr\.\s*/i,"") # Akademischen Grad loeschen
planviewFolder=$topFolder.Folders.Item($planviewFolderName)
archiveFolder=planviewFolder.Folders.Item($archiveFolderName)
archiveFolder.Items.each{ |mail|
subject=mail.Subject
(! subject.match(/#{$keyWord}/)) && die("outlook2Config: Betreff #{subject} enthaelt Begriff #{$keyWord} nicht")
sender=mail.SenderName
...
maskArr=subject.scan(/[0-9]{4}/)
#---------------------------------------------------------------
calendar.Items.each{ |appointment|
i+=1
if(appointment.entryID == entryID)
return appointment
end
}
#---------------------------------------------------------------
mail=sourceFolder.Items.GetFirst
mail.Move(targetFolder)
#---------------------------------------------------------------
while(planviewFolder.Items.Count != 0) do
mail=planviewFolder.Items.GetFirst
printf("Verschiebe %s in Ordner %s\n",mail.SenderName,$doneFolderName)
mail.Move(doneFolder)
end
IE/Edge
=========
$ie=WIN32OLE.new('InternetExplorer.Application'); checkValue($ie)
$ie.visible=true
Excel
=====
#############################################################################################
# Sensitivity-Label lesen
#############################################################################################
def getSensitivityLabel(file)
#--------------------------------------------------------------------------------------------------
# List das SensitivityLabel einer Excel-Datei, welche bereits (manuell) klassifiziert worden war
#--------------------------------------------------------------------------------------------------
begin
(! File.exists?(file)) && die("getSensitivityLabel: Datei #{file} existiert nicht")
#----------------------------------------------------------------------------------------------
unless($excel)
startExcel
end
#--------------------------------------------------------------------------------------------
# konvertieren ...
#--------------------------------------------------------------------------------------------
book=$excel.Workbooks.Open(file); checkValue(book)
labelInfo=book.SensitivityLabel.getlabel();
puts("LabelName: #{labelInfo.LabelName}");
puts("LabelId: #{labelInfo.LabelId}");
puts("SiteId: #{labelInfo.SiteId}");
puts("Assignment-Method: #{labelInfo.AssignmentMethod}");
rescue => exception
die("convertExcelCSVByNumber: #{exception.message}")
ensure
Dir.chdir($cwd)
end
end
#############################################################################################
# Sensitivity-Label setzen
#############################################################################################
def setSensitivityLabel(file)
#--------------------------------------------------------------------------------------------------
# Setzt das SensitivityLabel einer Excel-Datei
#--------------------------------------------------------------------------------------------------
begin
(! File.exists?(file)) && die("getSensitivityLabel: Datei #{file} existiert nicht")
#----------------------------------------------------------------------------------------------
unless($excel)
startExcel
end
#--------------------------------------------------------------------------------------------
# konvertieren ...
#--------------------------------------------------------------------------------------------
book=$excel.Workbooks.Open(file); checkValue(book)
labelInfo=book.SensitivityLabel.createLabelInfo()
labelInfo.AssignmentMethod=1 # MsoAssignmentMethod.PRIVILEGED
labelInfo.LabelId=LABELID
labelInfo.SiteId=SITEID
labelInfo.LabelName="Dr. Heinz Breinlinger"
book.SensitivityLabel.setLabel(labelInfo,labelInfo)
book.saveAs(file,ExcelConst::XlWorkbookDefault)
getSensitivityLabel(file);
rescue => exception
die("convertExcelCSVByNumber: #{exception.message}")
ensure
Dir.chdir($cwd)
end
end
#--------------------------------------------------------------------------------------------
# ';' in Text ersetzen, da csv-Trennzeichen
#--------------------------------------------------------------------------------------------
puts("Replacing ; in sheet #{sheetName} ...")
sheet.range("A1:ZZ1000").Replace({
"What" => ";",
"Replacement" => ","
})
#--------------------------------------------------------------------------------------------
# Zeilenumbrueche ersetzen
#--------------------------------------------------------------------------------------------
puts("Replacing ; in sheet #{sheetName} ...")
sheet.range("A1:ZZ1000").Replace({
"What" => "\n",
"Replacement" => " "
})
book.saveAs(file,ExcelConst::XlWorkbookDefault)
#---------------------------------------------------------------
sheet.Range("A1:C10").Clear
sheet.Range("A1:C10").ClearContents
book.worksheets(sheetNum).Cells.ClearContents
#---------------------------------------------------------------
book=$excel.Workbooks.add
sheet=book.Worksheets.add
#---------------------------------------------------------------
percFormat="0,00%"
currFormat="#.##0,00 \"Eur\";[Rot]-#.##0,00 \"Eur\""
floatFormat="#.##0,00;[Rot]-#.##0,00"
intFormat="#.##0;[Rot]-#.##0"
dateFormat="TT.MM.JJ"
timeFormat="hh:mm:ss"
sheet.cells(row,col).numberFormat=currFormat
sheet.range("A2:F60").numberFormat=currFormat
sheet.range("A"+row.to_s+":F"+row.to_s).horizontalAlignment=ExcelConst::XlCenter (..XlLeft ..XlRight)
#---------------------------------------------------------------
# Konvertierung
#---------------------------------------------------------------
book=$excel.Workbooks.Open(qualFile); checkValue(book)
book.saveAs(qualNewFile,ExcelConst::XlOpenXMLWorkbook)
book.close
#---------------------------------------------------------------
$excel=WIN32OLE.connect('Excel.Application')
$excel=WIN32OLE.new('Excel.Application'); checkValue($excel)
$excel.DisplayAlerts=false # verhindert Schlussfrage, ob gespeichert werden soll
WIN32OLE.const_load($excel,ExcelConst)
#---------------------------------------------------------------
book=$excel.Workbooks.Open(file); checkValue(book)
(1..book.worksheets.count).each{ |i|
sheetName=book.worksheets(i).Name
if(sheetName.match(/^#{name}/i))
...
#---------------------------------------------------------------
book=$excel.Workbooks.Open(file); checkValue(book)
book.worksheets(sheetNum).Activate
sheetName=book.worksheets(sheetNum).Name
book.saveAs(csvFile,ExcelConst::XlCSV) # alternativ: ExcelConst::XlCSVWindows|XlCSVMSDOS
book.close
#---------------------------------------------------------------
numSheets=book.worksheets.count
#---------------------------------------------------------------
# Zellformat-Wandlung
#
# "a4" => 4,1
#------------------------------------------------------------
(! cell.match(/^[[:alnum:]]+$/)) && die("excelExtractFromFile: Falsches Zellenformat 1: #{cell}")
(! cell.match(/^([[:alpha:]]+)([[:digit:]]+)$/)) && die("excelExtractFromFile: Falsches Zellenformat 2: #{cell}")
column=$1.upcase # "A"
row=$2 # "4"
(! $excelColumnMapReverse.key?(column)) && die("excelExtractFromFile: Spalte #{column} ist nicht in Mapping-Tabelle enthalten")
column=$excelColumnMapReverse[column]
row=row.to_i
column=column.to_i
text=book.worksheets(sheetNum).cells(row,column).Value.to_s # String-Wandlung
text=sheetNum.to_s+":"+cell.to_s+":"+text.encode!("ISO-8859-1")
#------------------------------------------------------------
book.worksheets(sheetNum).cells(row,column).Value=text
#------------------------------------------------------------
$excel.quit()
#------------------------------------------------------------
result=%x(tasklist /FI "IMAGENAME eq #{process}" /FI "PID ne #{$$}")
#------------------------------------------------------------
delete && sheet.Hyperlinks.Delete()
colChar=$excelColumnMap[col]
sheet.Hyperlinks.Add(sheet.Range(colChar+row.to_s),demandUrl,"",mouseOver,displayText)
sheet.Range(colChar+row.to_s).NumberFormat="@"
sheet.Range("A"+i.to_s+":Z"+i.to_s).Font.Size=8
sheet.Range("C"+i.to_s+":C"+i.to_s).NumberFormat="#,## \" %\""
sheet.cells(row,col).Value=cellContent.to_s
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sheet.Columns("A:Z").Autofit
$excel.activeWindow.DisplayZeros=0
book.SaveAs(fileName+".xlsx")
book.ExportAsFixedFormat(ExcelConst::XlTypePDF,fileName+".pdf",nil,true) # true ist "IgnorePrintAreas"
book.Close
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sheet=book.worksheets(1); checkValue(sheet)
#------------------------------------------------------------------------------------------------------------------------------------------------
book=$excel.Workbooks.Add; checkValue(book)
sheet=book.Worksheets.Add; checkValue(sheet)
sheet.Name="Anthologie"
sheet.Tab.Color=rgb(61,163,95)
sheet.Range("C2:D10000").NumberFormat="##.# \" Eur\""
sheet.Range("A"+row.to_s+":D"+row.to_s).Interior.ColorIndex=40
sheet.Range(3,8).Font.ColorIndex=6 # gelb
sheet.Range("A1:J2").Font.Bold=1
sheet.Range("A1:A10000").Autofilter(1,["Nova","Team"],ExcelConst::XlFilterValues)
sheet.Columns("A:Z").Autofit
$excel.activeWindow.DisplayZeros=0
#---------------------------------------------
# Standardtabellenblaetter loeschen
#---------------------------------------------
1.upto(1){ |i|
sheet=book.Worksheets("Tabelle"+i.to_s)
sheet=book.worksheets("Referat"); checkValue(sheet)
if(sheet)
sheet.Delete
end
}
book.Worksheets(1).Activate
#---------------------------------------------
comment=sheet.Range("I1:I1").AddComment
comment.Text("Fuer erweitere Ansicht in Spalte A \"Resource\" anhaken")
comment.Shape.TextFrame.AutoSize=true
comment.Visible=true
range=sheet.Range(sonstIstColChar+row.to_s)
range.Comment && range.Comment.Delete
#---------------------------------------------
def makeComment(cell,comment)
shape=cell.AddComment(comment).Shape
shape.Width=400
shape.Height=100
end
#---------------------------------------------
sheet.Range("A1:J1").Font.Bold=1
sheet.Range("A2:H2").Interior.ColorIndex=50
sheet.Range("A3:H3").Interior.ColorIndex=44
sheet.Range("C2").NumberFormat="# \" Tage\""
sheet.Range("C3:D1000").NumberFormat="##.# \" Eur\""
sheet.Range("E1:E1000").NumberFormat="#,## \" %\""
sheet.Range("F3:F1000").NumberFormat="[Rot]##.# \" Eur\";[Farbe10]-##.# \" Eur\""
sheet.Range("G3:G1000").NumberFormat="##.# \" Eur\""
sheet.Range("H3:H1000").NumberFormat="[Rot]##.# \" Eur\";[Farbe10]-##.# \" Eur\""
sheet.Range("A1:A1000").Autofilter(1,["Zeit","Projekt","Team"],ExcelConst::XlFilterValues)
sheet.Range("A"+row.to_s+":M"+row.to_s).Font.Bold=1
sheet.Range("A"+row.to_s+":M"+row.to_s).Borders(ExcelConst::XlEdgeBottom).LineStyle=ExcelConst::XlContinuous
sheet.Range("A"+row.to_s+":M"+row.to_s).Borders(ExcelConst::XlEdgeBottom).weight=ExcelConst::XlThin
sheet.Range("A"+row.to_s+":M"+row.to_s).Borders(ExcelConst::XlEdgeBottom).weight=ExcelConst::XlMedium
sheet.Range("A"+row.to_s+":M"+row.to_s).Borders(ExcelConst::XlEdgeBottom).ColorIndex=ExcelConst::XlAutomatic
sheet.Columns("A:Z").Autofit
$excel.activeWindow.SplitColumn=0
$excel.activeWindow.SplitRow=3
$excel.activeWindow.freezepanes=1 # Cave: Excel muss maximiert geoeffnet sein
$excel.activeWindow.DisplayZeros=0
sheet.Range("A1:M1").Autofilter
sheet.Columns("A:M").AutoFit
sheet.Columns("C:L").NumberFormat="0,0"
sheet.Range("A2").Select
$excel.activeWindow.freezepanes=1
$excel.activeWindow.DisplayZeros=0
book.SaveAs(Dir.getwd+"/Synopse.xls")
book.Close
#---------------------------------------------
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Rest-Formatierungen
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sheet.Range("A1:J1").Font.Bold=1
sheet.Range("A2:H2").Interior.ColorIndex=50
sheet.Range("A3:H3").Interior.ColorIndex=44
sheet.Range("C2").NumberFormat="# \" Tage\""
sheet.Range("E1:E1000").NumberFormat="#,## \" %\""
sheet.Range("F3:F1000").NumberFormat="[Rot]##.# \" Eur\";[Farbe10]-##.# \" Eur\""
sheet.Range("G3:G1000").NumberFormat="##.# \" Eur\""
sheet.Range("H3:H1000").NumberFormat="[Rot]##.# \" Eur\";[Farbe10]-##.# \" Eur\""
#-----------------------------------------------------------------
sheet.Range("A2").Select
$excel.ActiveWindow.FreezePanes=true
sheet.Columns("A:AZ").Autofit
sheet.Range("A2:AZ1000").Sort({"Key1" => sheet.Range("B2:B1000")})
#-----------------------------------------------------------------
sheet.Range("A1:Z1").Autofilter
sheet.Columns("A:Z").Autofit
sheet.Range("A1:Z1").Font.Bold=1
$excel.ActiveWindow.SplitColumn=0
$excel.ActiveWindow.SplitRow=1
$excel.ActiveWindow.FreezePanes=1
#- - - - - - - - - - - - - - - - - - - - - - -
# Blatt ans Ende stellen
# 'nil' ist der 'before'-Parameter von sheet.Move
# der zweite Parameter ist 'after'
#- - - - - - - - - - - - - - - - - - - - - - -
sheet.Move(nil,book.Worksheets(2)) # Sheet "Linie" ist Nummer 2, da "Team" davor als Nummer 1 gesetzt wurde
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Querformat fuer PDF-Export
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if($pdfExport)
sheet.PageSetup.Orientation=ExcelConst::XlLandscape
sheet.PageSetup.PrintArea="A1:H#{PRINTAREAROW}"
end
#- - - - - - - - - - - - - - - - - - - - - - -
# Standardtabellenblaetter loeschen
#- - - - - - - - - - - - - - - - - - - - - - -
1.upto(1){ |i|
sheet=book.Worksheets("Tabelle"+i.to_s)
if(sheet)
sheet.Delete
end
}
#- - - - - - - - - - - - - - - - - - - - - - -
# Sheet "Linie" aktivieren
#- - - - - - - - - - - - - - - - - - - - - - -
book.Worksheets(1).Activate
#- - - - - - - - - - - - - - - - - - - - - - -
book.SaveAs($cwd+"\\"+scope+"_"+$projName+".xlsx")
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# PDF-Export der Datei, d.h. beider Sheets
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if($pdfExport)
book.ExportAsFixedFormat(ExcelConst::XlTypePDF,$cwd+"\\"+scope+"_"+$projName+".pdf",nil,true) # true ist "IgnorePrintAreas"
end
#-----------------------------------------------------------------
rangeVist=sheet.Range(vistColChar+row.to_s)
#-----------------------------------------------------------------
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Cave: Hier muss die Blockform von "sub!" verwendet werden, da
# die Backreference $1 erst NACH Abschluss des Patternmatch gesetzt wird.
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
budget2=(tage*tagessatz).to_s
.sub!(/\./,",") # "." durch "," ersetzen
.sub!(/,(\d)$/) do # Bei einer Nachkommastelle "0" anhaengen
",#{$1}0"
end
.sub!(/(\d)(\d{3},)/) do # Tausendertrennzeichen "." setzen
"#{$1}.#{$2}"
end
Word
====
#---------------------------------------------------------------
doc=$word.Documents.Open(qualFile); checkValue(doc)
doc.saveAs2(qualNewFile,WordConst::WdFormatDocumentDefault)
doc.close
$word.quit()
#---------------------------------------------------------------
$word=WIN32OLE.connect('Word.Application'); checkValue($word)
$word=WIN32OLE.new('Word.Application'); checkValue($word); checkValue($word)
$word.Visible=1
$word.DisplayAlerts=false # verhindert Schlussfrage, ob gespeichert werden soll
WIN32OLE.const_load($word,WordConst)
#------------------------------------------------------------
if(replaceAll)
modifier=WordConst::WdReplaceAll
kind="alle Vorkommen"
else
modifier=WordConst::WdReplaceOne
kind="erstes Vorkommen"
end
content=doc.Content
find=content.find
#------------------------------------------------------------
doc=$word.Documents.Open(cwd+"/"+file); checkValue(doc)
text=doc.Range.Text
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# cf. https://docs.microsoft.com/en-us/office/vba/api/word.find.execute
# cf. in Word (Ctrl-h) die korrespondierenden Suchen- und Ersetzen-Parameter
#
# 1. FindText
# 2. MatchCase true
# 3. MatchWholeWord true
# 4. MatchWildCards false
# 5. MatchSoundsLike false
# 6. MatchAllWordForms false
# 7. Forward true
# 8. Wrap (am Dokumentende fortfahren)
# 9. Format false (Formatierung ist kein Kriterium)
# 10. ReplaceWith (Ersetzungs-String)
# 11. Replace wdReplaceAll (wdReplaceOne, wdReplaceNone)
# 12-15 vermutlich 4 aus: MatchPrefix, MatchSuffix, MatchPhrase, IgnoreSpace, IgnorePunct (nicht MatchKashida, MatchDicritics,
# MatchAlefHamza, MatchControl)
#
# 1 2 3 4 5 6 7 8 9 10 11 12-15
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
find.execute(toReplace,true,true,false,false,false,true,WordConst::WdFindContinue,false,replacement,modifier,false,false,false,false)
if(find.found)
...
doc.saveAs2($confDir+"\\"+$lbHash[VERTRAG]+"_Leistungsbeschreibung.docx")
#-----------------------------------------------------------------------------
# Checkboxen loeschen
#-----------------------------------------------------------------------------
doc.FormFields.each{ |field|
if(field.Type == WordConst::WdFieldFormCheckBox)
puts("Erasing checkbox #{i+=1} ...")
field.CheckBox.value=false
end
}
#-----------------------------------------------------------------------------
# Checkboxen setzen
#-----------------------------------------------------------------------------
checkBoxes=$contractHash["checkboxes"];
checkBoxes.split(',').each{ |name|
puts("Setting checkbox #{name} ...")
doc.FormFields(name).CheckBox.value=true; # Word wirft Fehler, wenn kein Form-Element dieses Namens vorhanden => keine Pruefung noetig
}
#-----------------------------------------------------------------------------
# Textersetzungen
#-----------------------------------------------------------------------------
wordReplace(doc,"<Hugo>","Willi")
#-----------------------------------------------------------------------------
# Textformularfeld loeschen/setzen
#-----------------------------------------------------------------------------
# doc.FormFields("datum").TextInput.Clear
# doc.FormFields("datum").Result="01.01.2024"
#-----------------------------------------------------------------------------
# Kalkulationstabelle einsetzen
#-----------------------------------------------------------------------------
# doc.ActiveWindow.Selection.InsertFile("C:\\Work_Config\\Budget\\Vertraege\\adesso\\Vertrag\\service-description.docx")
#-----------------------------------------------------------------------------
# Bild an Cursor-Position (Selection) einfuegen
#-----------------------------------------------------------------------------
# doc.ActiveWindow.Selection.InlineShapes.AddPicture("C:\\Work_Config\\Budget\\Vertraege\\adesso\\Vertrag\\calculation.png",false,true)
#-----------------------------------------------------------------------------
# Bild nach n. Buchstaben/Paragraphen einfuegen
#-----------------------------------------------------------------------------
# doc.Range(200).InlineShapes.AddPicture("C:\\Work_Config\\Budget\\Vertraege\\adesso\\Vertrag\\calculation.png",false,true)
# doc.Paragraphs(5).Range.InlineShapes.AddPicture("C:\\Work_Config\\Budget\\Vertraege\\adesso\\Vertrag\\calculation.png",false,true)
#-----------------------------------------------------------------------------
# Bild in (einzig) vorhandenes Inhaltssteuerelement (aus Entwicklertools)
# des Typs Bild einfuegen, d.h. das vorhandene Bild aendern
#-----------------------------------------------------------------------------
doc.ContentControls.each{ |contentControl|
if(contentControl.Type == WordConst::WdContentControlPicture)
puts("Found Picture-Control");
contentControl.Range.InlineShapes.AddPicture("C:\\Work_Config\\Budget\\Vertraege\\adesso\\Vertrag\\calculation.png",false,true)
end
}
#-----------------------------------------------------------------------------
# Anzahl der Zeichen einer Auswahl ausgeben (=> Ermittlung des Zeichenindex ab Anfang moeglich)
#-----------------------------------------------------------------------------
# puts("Zeichenzahl: #{doc.ActiveWindow.Selection.Characters.Count}")
#-----------------------------------------------------------------------------
# Bookmark loeschen
#-----------------------------------------------------------------------------
doc.Bookmarks.each{ |bookmark|
if(bookmark.Name == "definitions")
puts("Bookmark-Start: #{bookmark.Start}");
puts("Bookmark-End: #{bookmark.End}");
bookmark.Select
doc.ActiveWindow.Selection.Delete
end
}
top
===
R: Sortierreihenfolge umkehren
P: Nach CPU sortieren
M: nach Speicher sortieren
<>: Sortierspalte wechseln
j: Prozessnamen => rechts
blank: Update der Liste (unabhaengig vom eingestellten Intervall)
Toggle
1: Anzeige je CPU/Core
l: Last (1. Zeile)
1 == Auslastung bei 1 CPUs (Anzahl wartender Prozesse)
4 == Auslastung bei 4 CPUs
t: CPU/Task
Prozentual mit/ohne Balken
m: Memory (Prozent und xByte, je nach Option E)
E: KByte => Petabyte
B: Bold overall an/aus
b: Bold Sortierspalte/relevante Zeile vs. Blocksatz Sortierspalte/Zeile
x: Toggle sort field
V: Forst-View
v: mit Unterprozessen
c: Prozesse mit Pfadangabe
S: Zeitangabe
L Text: Prozessnamen "Text" finden (Cave: Keine '"')
&: naechsten Treffer finden
L <Return> Modus verlassen
f/F: Filterliste festlegen
s: Eintrag => Sortierkriterium
d/blank: Auswahl
<Rechtspfeil> <auf/ab>: Nach oben oder unten verschieben <Enter>
u "user": Nur Prozesse des Nutzers
A: 4-Fensteransicht
k: Signal an Prozess
Vorteil gegenueber mc: mc ist Teil von (Commandline-)WSL2 => kein GUI-Start von Microsoft-Anwendungen fuer Dateien,
Far Manager ist native TUI-Anwendung unter Windows
F1 Hilfe
Ctrl/Shift/Alt Hotkeyleiste zeigt nun Befehle fuer diese Sondertasten an
oder Kombinationen
Ctrl-L Toggle Information Panel
F3 auf directory Anzeige der Groesse in Spalte "Size" (View mit
F3 auf selection Anzeige der Groesse in Info-Zeile
Alt-F1/F2 change drive (links/rechts)
AltGr F7 nicht Alt-F7 => Find File
Ctrl-1,2,3 Toggle Panel (Spaltenzahl und Detailtiefe)
Ctrl-F12 Sort Mode
Ctrl-F3: Name
Ctrl-F4: Extension
Ctrl-F6: Size
Ctrl-F8: Creation Time
Ctrl-F9: Access Time
Alt-<Zeichenfolge> Suche nach Zeichenfolge
Alt-F8 History
Alt-F11 History File Views
Alt-F12 History Folders
Ctrl-B Toggle Hotkeyleiste unten
Alt-left/right Dateinamen scrollen
Alt-Pos1/End Dateinamen ganz links/rechts scrollen
Shift-up/down Auswaehlen (Cave: Ins wurde via Lua-Script remapped)
Ctrl-Page-Up Oberverzeichnis
Numpad: +/- Dateien per Regex an-/abwaehlen
Ins/Del: dito (qua Lua-Script) fuer Notebook ohne Numeric Pad
Numpad: Ctrl-+/- Alle Dateien mit Endung der aktuellen an-/abwaehlen
Numpad: Ctrl* Auswahl invertieren
Numpad: Shift-+/- Alle Dateien an-/abwaehlen
F9: Menue
Options => Editorsettings
<Pfad zu vi> "!.!"
/\
||
Variable fuer Langdateinamen
Ctrl-q: Quick-View
Ctrl-<Pfeil> Panelgroesse aendern
F3 View
F4 Editor (intern oder wie oben gesetzt)
F5,F6,F7,F8,F10,Esc analog mc
Alt-F8 Search-Dialogue
Shift-F8 (Editor) Auswahl Codepage
Alt-F12 Folder History
Ctrl-o Shell
Shift-F9 Save settings
Ctrl-Shift-1..9 Folder Shortcut
Cave: 0 funktioniert nicht
Cave: Ctrl-Shift-0..9 muss in Terminal-Emulation geloescht werden
Cave: Es gibt keine Erfolgsmeldung
=> F9 => Commands => Folder Shortcuts nachsehen
=> Kurzform: F9 c d
Right-Ctrl-1..9 Wechsel in Folder Shortcut
echo %FARPROFILE%
Profil ggf. auf anderen Rechner transplantieren
<path to Far Manager> /export settings.xml
<path to Far Manager> /import settings.xml
Makro-Dateien unter %FARPROFILE%\Macros\scripts\*.lua
F9 => Options => System Settings => Auto save setup
F9 => Options => Panel Settings => Select Folders (Unterverzeichnisse werden mitselektiert)
=> Show Free Size
=> Show Scrollbar