estrlist 5.96 KB
Newer Older
1
#!/bin/bash
Vitaly Lipatov's avatar
Vitaly Lipatov committed
2
# 2009-2010, 2012, 2017 Etersoft www.etersoft.ru
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
# Author: Vitaly Lipatov <lav@etersoft.ru>
# Public domain

# TODO: rewrite with shell commands, perl or C
# Python - http://www.linuxtopia.org/online_books/programming_books/python_programming/python_ch16s03.html
# Shell  - http://linux.byexamples.com/archives/127/uniq-and-basic-set-theory/
#        - http://maiaco.com/articles/shellSetOperations.php
# Perl   - http://docstore.mik.ua/orelly/perl/cookbook/ch04_09.htm
#        - http://blogs.perl.org/users/polettix/2012/03/sets-operations.html
# http://rosettacode.org/wiki/Symmetric_difference
# TODO: add unit tests
# http://ru.wikipedia.org/wiki/Операции_над_множествами

# Base set operations:
# * union
#   "1 2 3" "3 4 5" -> "1 2 3 4 5"
# * intersection
#   "1 2 3" "3 4 5" -> "3"
# * relative complement (substracted, difference) ( A ? B – members in A but not in B )
# http://en.wikipedia.org/wiki/Complement_%28set_theory%29
#   "1 3" "1 2 3 4" -> "2 4"
# * symmetric difference (симметричная разность) ( A ^ B – members in A or B but not both )
# http://en.wikipedia.org/wiki/Symmetric_difference
#   "1 2 3" "3 4 5" -> "1 2 4 5"

filter_strip_spaces()
{
        # possible use just
        #xargs echo
32
        sed -e "s| \+| |g" -e "s|^ ||" -e "s| \$||"
33 34 35 36 37 38 39
}

strip_spaces()
{
        echo "$*" | filter_strip_spaces
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
40 41 42 43 44
isempty()
{
        [ "$(strip_spaces "$*")" = "" ]
}

45
list()
46 47 48 49
{
        local i
        for i in $@ ; do
                echo "$i"
50 51 52
        done
}

53 54 55 56 57
count()
{
         list $@ | wc -l
}

58 59
union()
{
60
         strip_spaces $(list $@ | sort -u)
61 62
}

63 64 65 66
uniq()
{
        union $@
}
67

68 69 70 71
has()
{
	local wd="$1"
	shift
72
	echo "$*" | grep -q -- "$wd"
73 74
}

75 76 77 78 79 80 81 82 83
# Note: used egrep! write '[0-9]+(first|two)', not '[0-9]\+...'
match()
{
	local wd="$1"
	shift
	echo "$*" | egrep -q -- "$wd"
}


84 85
# remove_from_list "1." "11 12 21 22" -> "21 22"
reg_remove()
86 87 88 89 90 91 92 93 94 95 96
{
        local i
        local RES=
        for i in $2 ; do
                echo "$i" | grep -q "$1" || RES="$RES $i"
        done
        strip_spaces "$RES"
}

# remove_from_list "1." "11 12 21 22" -> "21 22"
reg_wordremove()
97 98 99 100 101 102 103 104 105 106
{
        local i
        local RES=
        for i in $2 ; do
                echo "$i" | grep -q -w "$1" || RES="$RES $i"
        done
        strip_spaces "$RES"
}

# Args: LIST1 LIST2
107
# do_exclude_list print LIST2 list exclude fields contains also in LIST1
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
# Example: exclude "1 3" "1 2 3 4" -> "2 4"
exclude()
{
        local i
        local RES=
        for i in $2 ; do
                echo "$1" | grep -q -w "$i" || RES="$RES $i"
        done
        strip_spaces "$RES"
}

# regexclude_list "22 1." "11 12 21 22" -> "21"
reg_exclude()
{
        local i
        local RES="$2"
        for i in $1 ; do
                RES=$(reg_remove "$i" "$RES")
        done
        strip_spaces "$RES"
}

130 131 132 133 134 135 136 137 138 139 140
# regexclude_list "22 1." "11 12 21 22" -> "21"
reg_wordexclude()
{
        local i
        local RES="$2"
        for i in $1 ; do
                RES=$(reg_wordremove "$i" "$RES")
        done
        strip_spaces "$RES"
}

141 142 143 144 145 146 147 148 149 150 151 152
# FIXME:
# reg_include "1." "11 12 21 22" -> "11 12"
reg_include()
{
        local i
        local RES=
        for i in $2 ; do
                echo "$i" | grep -q -w "$1" && RES="$RES $i"
        done
        strip_spaces "$RES"
}

153 154 155 156 157 158 159 160
example()
{
        local CMD="$1"
        local ARG1="$2"
        shift 2
        echo "\$ $0 $CMD \"$ARG1\" \"$@\""
        $0 $CMD "$ARG1" "$@"
}
161

162 163 164 165 166
example_res()
{
	example "$@" && echo TRUE || echo FALSE
}

167
help()
168 169 170 171
{
        echo "estrlist developed for string list operations. See also cut, join, paste..."
        echo "Usage: $0 <command> [args]"
        echo "Commands:"
172 173 174 175
        echo "  strip_spaces [args]               - remove spaces between words"
        echo "  filter_strip_spaces               - remove spaces from words from standart input"
        echo "  reg_remove  <PATTERN> [word list] - remove words containing a match to the given PATTERN (grep notation)"
        echo "  reg_wordremove  <PATTERN> [word list] - remove words containing a match to the given PATTERN (grep -w notation)"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
176 177 178
        echo "  exclude <list1> <list2>           - print list2 words exclude list1 items"
        echo "  reg_exclude <PATTERN> [word list] - print only words do not matched with PATTERN"
        echo "  reg_wordexclude <PATTERN> [word list] - print only words do not matched with PATTERN"
179 180
        echo "  has <PATTERN> string              - check the string for a match to the regular expression given in PATTERN (grep notation)"
        echo "  match <PATTERN> string            - check the string for a match to the regular expression given in PATTERN (egrep notation)"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
181
        echo "  isempty [string]                  - true if string has no any symbols (only zero or more spaces)"
182 183 184 185
        echo "  union [word list]                 - sort and remove duplicates"
        echo "  uniq [word list]                  - alias for union"
        echo "  list [word list]                  - just list words line by line"
        echo "  count [word list]                 - print word count"
186 187
        echo
        echo "Examples:"
188 189 190 191 192 193 194
        example reg_remove "1." "11 12 21 22"
        example reg_wordremove "1." "11 12 21 22"
        example exclude "1 3" "1 2 3 4"
        example reg_exclude "22 1." "11 12 21 22"
        example reg_wordexclude "wo.* er" "work were more else"
        example union "1 2 2 3 3"
        example count "1 2 3 4 10"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
195 196
        example_res isempty "  "
        #example_res isempty " 1 "
197 198
        example_res has ex "exactly"
        example_res has exo "exactly"
199 200
        example_res match "M[0-9]+" "M250"
        example_res match "M[0-9]+" "MI"
201 202 203 204 205 206 207 208
}

COMMAND="$1"
if [ -z "$COMMAND" ] ; then
        echo "Run with --help for get command description."
        exit 1
fi

209 210 211 212
if [ "$COMMAND" = "-h" ] || [ "$COMMAND" = "--help" ] ; then
        COMMAND="help"
fi

213
shift
214 215

# FIXME: do to call function directly, use case instead?
216 217
if [ "$1" = "-" ] ; then
    shift
218
    "$COMMAND" "$(cat) $@"
219 220
elif [ "$2" = "-" ] ; then
    "$COMMAND" "$1" "$(cat)"
221 222 223
else
    "$COMMAND" "$@"
fi