home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sys / next / misc / 23024 / cut
Encoding:
Text File  |  1992-12-14  |  4.0 KB  |  182 lines

  1. #!/bin/sh
  2. # Shell/awk version of System V cut(1) command
  3. # Is not fully compatible, nor optimized (-c option is SLOW).
  4. # Incompatibilities include
  5. #  - Different diagnostics
  6. #  - Arbitrary limits on number of columns/fields it will output
  7. #  - Does not process delimiter-less records properly
  8. #  - Does not implement the -s option
  9.  
  10. # Written by Jon LaBadie (princeton!jonlab!jon) in July, 1990 while
  11. # teaching a UNIX Tools class on a Xenix system that did not include
  12. # cut.  The command was needed for some of the class exercises.
  13.  
  14. # In no way would I recommend it be used as a replacement for cut(1).
  15. # But if you need the capabilities of cut, this might do.
  16.  
  17. # set -u
  18.  
  19. PROG=${0}
  20.  
  21. usage() {
  22.     # usage message should be revised to include -d option
  23.     echo "Usage:  ${PROG} -{f|c}spec [file(s)]" >&2
  24.     echo "  where:  spec is m,n or m-n, or n-" >&2
  25.     exit 1
  26. }
  27.  
  28. COLUMNS=FALSE
  29. FIELDS=FALSE
  30. DELIM=FALSE
  31.  
  32. while [ ${#} -gt 0 ]
  33. do
  34.     case "${1}"
  35.     in
  36.     -f*)    [ ${COLUMNS} != FALSE ] && usage
  37.         FIELDS=`expr "${1}" : '..\(.*\)'`
  38.         [ "${FIELDS}" = "" ] && {
  39.             echo "${PROG}: -f option requires an argument" >&2
  40.             usage
  41.         }
  42.         ;;
  43.     -c*)    [ ${FIELDS} != FALSE ] && usage
  44.         COLUMNS=`expr "${1}" : '..\(.*\)'`
  45.         [ "${COLUMNS}" = "" ] && {
  46.             echo "${PROG}: -c option requires an argument" >&2
  47.             usage
  48.         }
  49.         ;;
  50.     -d)    echo "${PROG}: -d option requires a single character argument" >&2
  51.         usage
  52.         ;;
  53.     -d?)    DELIM=`expr "${1}" : '..\(.*\)'`
  54.         ;;
  55.     -d??*)    echo "${PROG}: single character delimiters only" >&2
  56.         exit 1
  57.         ;;
  58.     -?*)    echo "${PROG}: Illegal Option: \"${1}\"" >&2
  59.         usage
  60.         ;;
  61.     *)    break    # start of file names
  62.         ;;
  63.     esac
  64.     shift
  65. done
  66.  
  67. [ "${FIELDS}" = FALSE -a "${COLUMNS}" = FALSE ] && {
  68.     echo "${PROG}: either -f or -c option must be used" >&2
  69.     usage
  70. }
  71.  
  72. [ "${DELIM}" != FALSE -a "${COLUMNS}" != FALSE ] && {
  73.     echo "${PROG}: -d and -c options are incompatible" >&2
  74.     usage
  75. }
  76.  
  77. [ "${DELIM}" = FALSE ] && DELIM='    '   # TAB character
  78.  
  79. FILES=${@+"${@}"}
  80.  
  81. if [ "${FIELDS}" != FALSE ]
  82. then
  83.     awk -F"${DELIM}" '
  84.     BEGIN {
  85.         OFS = "'"${DELIM}"'"
  86.         stderr = "/dev/tty"
  87.  
  88.         n = split("'"${FIELDS}"'", tmp1, ",")
  89.         j = 0
  90.  
  91.         for (i = 1; i <= n; i++) {
  92.             if ( (pos = index(tmp1[i], "-")) == 0) {
  93.                 # must be simple n type column spec
  94.                 cols[++j] = tmp1[i] + 0;
  95.             }
  96.             else if (pos == length(tmp1[i])) {
  97.                 # must be n- type column specifier
  98.                 if (i != n) {
  99.                     print "'"${PROG}"'" ": Field specifier " tmp1[i] ", must be last" > stderr
  100.                     exit 1
  101.                 }
  102.                 v = substr(tmp1[i], 1, pos - 1) + 0
  103.                 while (j < 48)  #  arbitrary max of 48
  104.                     cols[++j] = v++
  105.             }
  106.             else {
  107.                 # last possibility is m-n type
  108.                 n2 = split(tmp1[i], tmp2, "-")
  109.                 while (tmp2[1] <= tmp2[2])
  110.                     cols[++j] = tmp2[1]++ + 0
  111.             }
  112.         }
  113.         ncols = j
  114.         for (i = 1; i < ncols; i++)
  115.             if (cols[i] >= cols[i+1]) {
  116.                 print "'"${PROG}"'" ": Fields must be specified in ascending order" >stderr
  117.                 exit 1
  118.             }
  119.     }
  120.  
  121.     {
  122.         printf("%s", $(cols[1]))
  123.         for (i = 2; i <= ncols && cols[i] <= NF; i++) {
  124.             printf("%s%s", OFS, $(cols[i]))
  125.         }
  126.         print ""
  127.     }
  128.     ' ${FILES}
  129. else
  130. # must be -c option
  131.     awk '
  132.     BEGIN {
  133.         stderr = "/dev/tty"
  134.  
  135.         n = split("'"${COLUMNS}"'", tmp1, ",")
  136.         j = 0
  137.  
  138.         for (i = 1; i <= n; i++) {
  139.             if ( (pos = index(tmp1[i], "-")) == 0) {
  140.                 # must be simple n type column spec
  141.                 cols[++j] = tmp1[i] + 0;
  142.             }
  143.             else if (pos == length(tmp1[i])) {
  144.                 # must be n- type column specifier
  145.                 if (i != n) {
  146.                     print "'"${PROG}"'" ": Column specifier " tmp1[i] ", must be last" > stderr
  147.                     exit 1
  148.                 }
  149.                 v = substr(tmp1[i], 1, pos - 1) + 0
  150.                 while (j < 200)  #  arbitrary max of 200
  151.                     cols[++j] = v++
  152.             }
  153.             else {
  154.                 # last possibility is m-n type
  155.                 n2 = split(tmp1[i], tmp2, "-")
  156.                 while (tmp2[1] <= tmp2[2])
  157.                     cols[++j] = tmp2[1]++ + 0
  158.             }
  159.         }
  160.         ncols = j
  161.         for (i = 1; i < ncols; i++)
  162.             if (cols[i] >= cols[i+1]) {
  163.                 print "'"${PROG}"'" ": Columns must be specified in ascending order" >stderr
  164.                 exit 1
  165.             }
  166.     }
  167.  
  168.     {
  169.         printf("%s", substr($0, cols[1], 1))
  170.         l = length
  171.         for (i = 2; i <= ncols && cols[i] <= l; i++) {
  172.             printf("%s", substr($0, cols[i], 1))
  173.         }
  174.         print ""
  175.     }
  176.     ' ${FILES}
  177. fi
  178.  
  179. exit 0
  180.  
  181.  
  182.