Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect and remove indentation of a piped text

Tags:

bash

unix

pipe

I'm looking for a way to remove the indentation of a piped text. Below is a solution using cut -c 9- which assumes the indentation is 8 character wide.

I'm looking for a solution which can detect the number of spaces to remove. This implies going through the whole (piped) file to know the minimum number of spaces (tabs?) used to indent it, then remove them on each line.

run.sh

help() {
    awk '
    /esac/{b=0}
    b
    /case "\$arg" in/{b=1}' \
    "$me" \
    | cut -c 9-
}

while [[ $# -ge 1 ]]
do
    arg="$1"
    shift
    case "$arg" in
        help|h|?|--help|-h|'-?')
            # Show this help
            help;;
    esac
done

$ ./run.sh --help

help|h|?|--help|-h|'-?')
    # Show this help
    help;;

Note: echo $' 4\n 2\n 3' | python3 -c 'import sys; import textwrap as tw; print(tw.dedent(sys.stdin.read()), end="")' works but I expect there is a better, way (I mean, one which doesn't only depends on software more common than python. Maybe awk? I wouldn't mind seeing a perl solution either.

Note2: echo $' 4\n 2\n 3' | python -c 'import sys; import textwrap as tw; print tw.dedent(sys.stdin.read()),' also works (Python 2.7.15rc1).

like image 245
Mathieu CAROFF Avatar asked Dec 31 '25 01:12

Mathieu CAROFF


2 Answers

The following is pure bash, with no external tools or command substitutions:

#!/usr/bin/env bash
all_lines=( )
min_spaces=9999 # start with something arbitrarily high
while IFS= read -r line; do
  all_lines+=( "$line" )
  if [[ ${line:0:$min_spaces} =~ ^[[:space:]]*$ ]]; then
    continue  # this line has at least as much whitespace as those preceding it
  fi
  # this line has *less* whitespace than those preceding it; we need to know how much.
  [[ $line =~ ^([[:space:]]*) ]]
  line_whitespace=${BASH_REMATCH[1]}
  min_spaces=${#line_whitespace}
done

for line in "${all_lines[@]}"; do
  printf '%s\n' "${line:$min_spaces}"
done

Its output is:

  4
2
 3
like image 108
Charles Duffy Avatar answered Jan 01 '26 17:01

Charles Duffy


Suppose you have:

$ echo $'    4\n  2\n   3\n\ttab'
    4
  2
   3
    tab

You can use the Unix expand utility to expand the tabs to spaces. Then run through an awk to count the minimum number of spaces on a line:

$ echo $'    4\n  2\n   3\n\ttab' | 
expand | 
awk 'BEGIN{min_indent=9999999}
     {lines[++cnt]=$0
      match($0, /^[ ]*/)
      if(RLENGTH<min_indent) min_indent=RLENGTH
     }
     END{for (i=1;i<=cnt;i++) 
               print substr(lines[i], min_indent+1)}'
  4
2
 3
      tab
like image 26
dawg Avatar answered Jan 01 '26 18:01

dawg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!