0

Often I have code that I want to align based on similar structure of lines, not just the left-side auto indent. Is there a script out there that can do something like this? Here is an example of what I want to do. Given:

 self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop ... 

I want to run a script and align each "column" on a tab so that they are aligned and easier to visually parse:

 self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop ... 

I am thinking that a Perl or Python or AWK or some other scripting language could do this, but alas I know none of these. Till now I have been using Vim and its regex based substitution capabilities but I still spend most of the time manually spacing out the columns.

9
  • 1
    Does each column actually begin with a tab or several whitespace characters or is that just the way that you have it formatted here? Also, are there always three columns?CommentedNov 28, 2020 at 4:31
  • Emacs has align-regexp. Are you looking for the column program?
    – icarus
    CommentedNov 28, 2020 at 4:51
  • if you used a program to add some directives in the raw text, you could probably get tbl and nroff to format things how you like in monospaced ASCII, Been a while since I used them, so I can't make a detailed answer
    – infixed
    CommentedNov 28, 2020 at 5:15
  • @NasirRiley The column may be tab-aligned (with tab character) or space character, it doesn't matter to me as long as they look aligned -- I think though using a space would be the preferred solution as it is tab-length independent. There could be more than 3 columns, but this is the typical scenario. The idea is to have these similar parts of a line aligned vertically.
    – andrewz
    CommentedNov 28, 2020 at 7:12
  • Do you have any quoted strings (e.g. "foo bar") or comments or anything else in your input file that might contain blanks that you do not want to be considered "column" separators?
    – Ed Morton
    CommentedNov 28, 2020 at 17:24

3 Answers 3

2

This will give you the expected result

File.txt :

self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop 

When below command is used :

sed 's/^[[:blank:]]*//' File.txt | column -t -s " " 

This command will remove frontend spaces : sed 's/^[[:blank:]]*//' refer this stack overflow Question , explained in detail with an example what actually the command does stack overflow : click_here

Syntax :column -t [-s separator] [filename] -> column -t -s " "

–t : parameter to display the content in tabular format

-s : To separate the content based on a specific delimiter

Output of command :

self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop 

Make sure before you make use of above command just align your entire data in file to left side in order to align data i have used : sed 's/^[[:blank:]]*//'

3
  • I noticed that the -s " " character gets eaten if I specify something else, ex. -s ":" for lines that look like this "parameter: type" results in "parameter type". Is there a way not to eat that character? I was expecting "parameter : type".
    – andrewz
    CommentedNov 28, 2020 at 7:21
  • @andrewz yes i agree with you what you said but the user as provided the input content like that with spaces ,if the input data was separated by : then yours's one will work like charm for thatCommentedNov 28, 2020 at 9:44
  • I edited your answer because you don't need to pipe cat into sed. sed can be run directly against the file.CommentedNov 28, 2020 at 12:59
2

Even though you've already accepted an answer, the result that you want can obtained with just one awk or sed command without having to pipe it into the column command.

awk '{print $1"\t\t"$2"\t\t"$3}' column.txt sed -e 's/^[[:blank:]]*//' -e 's|\s|\t\t|g' column.txt 

The sed command first removes all blank space at the beginning of each line and then converts any remaining spaces into two tabs. It gives this output:

self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop 

The awk command prints just the first column which are the strings beginning with self and then prints two tabs, the second column which is =?, another two tabs, and finally, the string in the third column.

self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop 

To edit the file itself instead of sending it to standard output, use either of the following:

sed -i -e 's/^[[:blank:]]*//' -e 's|\s|\t\t|g' column.txt awk -i inplace '{print $1"\t\t"$2"\t\t"$3}' column.txt 

The awk command requires version 4.2 or later to have the -i inplace switch.

2
  • Awesome bro i like your logic of awk , can you tell what is the meaning of inplaceCommentedNov 28, 2020 at 13:52
  • It is for editing the file inplace. The -i switch for sed is the same. I edited the awk command a little to have it give the exact same output as the sed command.CommentedNov 28, 2020 at 14:33
2

All you need is:

$ column -t file self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop 

or if you prefer:

$ column -t -o' ' file self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop $ column -t -o$'\t' file self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop $ column -t -o$'\t\t' file self.colorOfBackground =? colorOfBackground self.colorOfLineForTime =? colorOfLineForTime self.marginOnBottom =? marginOnBottom self.marginOnTop =? marginOnTop 

Massage the column arguments to suit.

3
  • 1
    This is the simplest solution I've seen here. Very nice.
    – andrewz
    CommentedNov 29, 2020 at 1:30
  • This is actually the better answer because it aligns into columns the entire line, which is more generic and applicable to other cases. Unfortunately I didn't phrase the question that way as I didn't expect such a complex problem to be solvable in such an easy way. Xcode should have a formatting feature like this, to simply invoke 'column -t' over selected lines; this would save me from copy/pasting into a unix terminal and running the command.
    – andrewz
    CommentedDec 3, 2020 at 17:24
  • Even in vi you can define macros to call a command on a selected set of lines and replace that set of lines with the result so it'd be shocking if Xcode didn't also have that. You might want to search the archives for xcode questions and then post one tagged with xcode if you can't find an existing answer.
    – Ed Morton
    CommentedDec 3, 2020 at 18:45

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.