The parameters to the script are an indentation character c and a number of characters per level n, these parameters are followed by a list of files (if no files are provided, standard input is used). The script then reads line by line and on each line it removes the white characters at the beginning of line and replaces them with k*n characters c where k is the level of bracket nesting. Consider normal brackets (), curly brackets {} and square brackets []. For example the input file

a ( b 
     c d [ e ] f [
  g h { j (
            k ) } l m
     n ] o ) p
q r
would be modified as follows if the script is run with parameters c='.' and n=1:
a ( b
.c d [ e ] f [
..g h { j (
....k ) } l m
..n ] o ) p
q r

(assume that the input has well paired brackets. A space or a tab character must be allowed as character c)

  • 2
    What has your class learned recently that might be relevant to how you're meant to do this? May 8 '19 at 6:33
  • I'm voting to close this question as off-topic because it sound a lot like homework
    – Kiwy
    May 10 '19 at 9:12
  • vim -c "execute 'normal! =G' | :wq! <OUT_FILE>" <FILE> Oct 21 '19 at 7:49

"How to write a script": you break the problem into smaller steps that are easier to translate into code:

  1. read your file one line at a time
  2. count the number of open/close brackets, and update the running total accordingly
    • this can be done by processing the line one character at a time, or by other means
  3. create a string of c characters that is "running total" characters long
  4. print that string and the line.
  5. think about edge cases and error conditions: given the assumption in your question, this would be for extra credit I guess:
    • what happens if the running total becomes negative
    • what happens if the running total at the end of the file is greater than zero

Here's my proposed solution. I took your example as input. The idea is :

  1. delete all existing indents
  2. read the input line by line
  3. in each line, count the number of opening brackets : ( and [ and { and increase the "indent level" accordingly
  4. for the same line, count closing brackets and decrease the "indent level"
  5. substitute variables since opening brackets cause the following line to be indented
  6. generate the "indent string", which is the "indent character" repeated "indent level" times
  7. output the "indent string" + contents of each line
  8. repeat until the end of the input

#!/usr/bin/env bash

fileToReindent='./testFile' indentCharacter='.'

countOccurrencesOfNeedleInHaystack() { local needle=$1 local haystack=$2 echo "$haystack" | grep -o "$needle" | wc -l }

makeIndentString() { local indentCharacter=$1 local indentLevel=$2 python -c "print('$indentCharacter' * $indentLevel)" }

# delete all existing indents sed -ri 's/^ (.)$/\1/' "$fileToReindent"

# indent lines indentLevelOfCurrentLine=0 indentLevelOfNextLine=0

while read line; do for character in '(' '[' '{'; do nb=$(countOccurrencesOfNeedleInHaystack "$character" "$line") indentLevelOfNextLine=$((indentLevelOfNextLine+nb)) done for character in ')' ']' '}'; do nb=$(countOccurrencesOfNeedleInHaystack "$character" "$line") indentLevelOfNextLine=$((indentLevelOfNextLine-nb)) done indentString=$(makeIndentString "$indentCharacter" "$indentLevelOfCurrentLine") indentLevelOfCurrentLine=$indentLevelOfNextLine echo "$indentString$line" done < "$fileToReindent"

NB : this code is just a proof of concept and still needs polish.

NB2 : having issues with extra blank lines in rendered block of code. Edits welcome ;-)

  • Can someone explain the downvote ? (just looking to avoid mistakes / improve future answers)
    – Httqm
    May 15 '19 at 14:41