Home > Mobile >  Multiline output to single line concatenation with delimiter string
Multiline output to single line concatenation with delimiter string

Time:06-18

I use this command to get a list of all the files that has changed in a pull-request.

git diff --name-only HEAD master

Sample output:

my/repo/file1.java
my/repo/file3.java
my/repo/file5.java

I would like to convert this output to the following:

file:my/repo/file1.java||file:my/repo/file3.java||file:my/repo/file5.java

so that I can run code analysis only on these files from IntelliJ IDEA.

What have I tried so far?

git diff --name-only HEAD master |  sed -e 's/^/file:/'  | paste -s -d "||" -

This gives me the following output:

file:my/repo/file1.java|file:my/repo/file3.java|file:my/repo/file5.java

Notice the single |.

Also, please simplify the command if possible.

CodePudding user response:

You may try this git... | awk solution:

git diff --name-only HEAD master |
awk '{printf "%sfile:%s", (NR>1?"||":""), $0} END{print ""}'

Or a more nifty awk solution (works with BSD/Mac awk also):

git diff --name-only HEAD master |
awk -v RS= -v OFS='||' '{$1=$1} 1'

CodePudding user response:

Using sed

$ git diff --name-only HEAD master| sed s'/^/file:/;:a;N;s/\n/||file:/;ba'
file:my/repo/file1.java||file:my/repo/file3.java||file:my/repo/file5.java

CodePudding user response:

You can also do it with awk

git diff --name-only HEAD master |
awk 'NR > 1 {printf("||")} {printf("file:%s",$0)} END{print ""}'

What this awk does is:

  • for all input lines but the first, output: ||
  • for all input lines, output: file: <input line content>
  • when there's no more input lines to read, output a newline character

remark: the END{print ""} is unrequited when you do out=$(git .. | awk ...)

CodePudding user response:

Since you're on a Mac, might as well use zsh instead of its ancient outdated version of bash (Plus no using extra processes or programs, just zsh substitutions):

#!/usr/bin/env zsh                                                                                                                                                                                                                               

#data=$(git diff --name-only HEAD master)

data="my/repo/file1.java                                                                                                                                                                                                                       
my/repo/file3.java                                                                                                                                                                                                                               
my/repo/file5.java"

typeset -a files=( "${(@f)data}" ) # Split on newlines
combined=${(j:||:)files[@]/#/file:} # Add file: to every element and join with ||

# file:my/repo/file1.java||file:my/repo/file3.java||file:my/repo/file5.java
print "$combined" 

CodePudding user response:

The list of delimiters to paste is a list of consecutive single-character delimiters to be used for columns.

$ paste -d 'abc' <(seq 0 3) <(seq 3 6) <(seq 6 9) <(seq 9 12)
0a3b6c9
1a4b7c10
2a5b8c11
3a6b9c12

There is a simple trick - you can make paste join lines with a single-char delimiter, and then replace the single char by multi-char that you want to have.

git diff --name-only HEAD master | paste -sd '|' | sed 's/|/||/g'

You can also use bash to replace newlines with ||. Fun fact: command substitution $(..) removes trailing newlines.

a=$(git diff --name-only HEAD master); echo "${a//$'\n'/||}"

CodePudding user response:

Since you're on macOS you can use perl

git diff --name-only HEAD master |
perl -pe 's/^/file:/; s/\n/||/ unless eof'
  • Related