source: vendor/bash/3.1-p17/examples/scripts.v2/pages

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 4.5 KB
Line 
1#! /bin/bash
2#
3# original from:
4# @(#) pages.sh 1.0 92/09/26
5# 92/09/05 John H. DuBois III (jhdiii@armory.com)
6# 92/09/26 Added help
7#
8# conversion to bash v2 syntax by Chet Ramey
9
10Usage="$0 [-h] [-n lines/page] page-ranges [file ...]"
11
12usage()
13{
14 echo "$Usage" 1>&2
15}
16
17phelp()
18{
19echo "$0: print selected pages.
20Usage: $Usage
21
22If no file names are given, the standard input is read.
23
24The input is grouped into pages and a selected subset of them is printed.
25Formfeeds are acted on correctly.
26
27If the output device does automatic line wrap, lines that longer than
28the width of the output device will result in incorrect output.
29The first non-option argument is a list of pages to print.
30
31Pages are given as a list of ranges separated by commas.
32A range is either one number, two numbers separted by a dash,
33or one number followed by a dash. A range consisting of one
34number followed by a dash extends to the end of the document.
35
36Options:
37-n sets the number of lines per page to n. The default is 66."
38}
39
40while getopts "n:h" opt; do
41 case "$opt" in
42 n) LinesPerPage=$OPTARG;;
43 h) phelp; exit 0;;
44 *) usage; exit 2;;
45 esac
46done
47
48shift $(($OPTIND - 1))
49
50if [ $# -eq 0 ]; then
51 echo $0: no page ranges given. 1>&2
52 usage
53 exit 1
54fi
55
56PageList=$1
57shift
58
59gawk "
60BEGIN {
61 PageList = \"$PageList\"; LinesPerPage = \"$LinesPerPage\""'
62 if (LinesPerPage == "")
63 LinesPerPage = 66
64 else
65 if (LinesPerPage !~ "[1-9][0-9]*")
66 ErrExit("Bad value for lines per page: " LinesPerPage)
67 LinesPerPage += 0
68 NumRanges = split(PageList,Ranges,",")
69 for (i = 1; i <= NumRanges; i++) {
70 if ((StartRange = EndRange = Ranges[i]) !~ "^[0-9]+(-([0-9]+)?)?$")
71 ErrExit("Bad range \"" StartRange "\"")
72 sub("-.*","",StartRange)
73 sub(".*-","",EndRange)
74 if (EndRange == "")
75 EndRange = 2 ^ 30
76 # Force StartRange and EndRange to be numeric values
77 if ((StartRange += 0) == 0 || (EndRange += 0) == 0)
78 ErrExit("Invalid page number \"0\" in range " Ranges[i])
79 if (StartRange > EndRange)
80 ErrExit("Start page comes after end page in range " Ranges[i])
81 TmpRangeStarts[i] = StartRange
82 TmpRangeEnds[i] = EndRange
83 }
84
85 # Sort ranges
86 qsort(TmpRangeStarts,k)
87 RangeEnds[0] = 0
88 for (i = 1; i <= NumRanges; i++) {
89 RangeEnds[i] = TmpRangeEnds[k[i]]
90 if ((RangeStarts[i] = TmpRangeStarts[k[i]]) <= RangeEnds[i - 1])
91 ErrExit("Overlapping ranges: " Ranges[k[i]] "," Ranges[k[i - 1]])
92 }
93
94 RangeNum = LineNum = PageNum = 1
95 InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
96 FS = "\014"
97}
98
99{
100 if (LineNum > LinesPerPage)
101 NewPage()
102 if (InRange)
103 printf "%s",$1
104 # Deal with formfeeds
105 for (i = 2; i <= NF; i++) {
106 if (InRange)
107 printf "\014"
108 NewPage()
109 if (InRange)
110 printf "%s",$i
111 }
112 if (InRange)
113 print ""
114 LineNum++
115}
116
117function NewPage() {
118 PageNum++
119 LineNum = 1
120 # At the start of each page, check whether we are in a print range
121 WereInRange = InRange
122 InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
123 # If last page was in range and we no longer are, move to next range
124 if (WereInRange && !InRange && ++RangeNum > NumRanges)
125 exit
126}
127
128function In(a,Min,Max) {
129 return (Min <= a && a <= Max)
130}
131
132function ErrExit(S) {
133 print S > "/dev/stderr"
134 Err = 1
135 exit 1
136}
137
138# Arr is an array of values with arbitrary indices.
139# Array k is returned with numeric indices 1..n.
140# The values in k are the indices of array arr,
141# ordered so that if array arr is stepped through
142# in the order arr[k[1]] .. arr[k[n]], it will be stepped
143# through in order of the values of its elements.
144# The return value is the number of elements in the array (n).
145function qsort(arr,k, ArrInd,end) {
146 end = 0
147 for (ArrInd in arr)
148 k[++end] = ArrInd;
149 qsortseg(arr,k,1,end);
150 return end
151}
152
153function qsortseg(arr,k,start,end, left,right,sepval,tmp,tmpe,tmps) {
154 # handle two-element case explicitely for a tiny speedup
155 if ((end - start) == 1) {
156 if (arr[tmps = k[start]] > arr[tmpe = k[end]]) {
157 k[start] = tmpe
158 k[end] = tmps
159 }
160 return
161 }
162 left = start;
163 right = end;
164 sepval = arr[k[int((left + right) / 2)]]
165 # Make every element <= sepval be to the left of every element > sepval
166 while (left < right) {
167 while (arr[k[left]] < sepval)
168 left++
169 while (arr[k[right]] > sepval)
170 right--
171 if (left < right) {
172 tmp = k[left]
173 k[left++] = k[right]
174 k[right--] = tmp
175 }
176 }
177 if (left == right)
178 if (arr[k[left]] < sepval)
179 left++
180 else
181 right--
182 if (start < right)
183 qsortseg(arr,k,start,right)
184 if (left < end)
185 qsortseg(arr,k,left,end)
186}
187' "$@"
Note: See TracBrowser for help on using the repository browser.