How to Merge Two Rows in a Same Row from a Text File in Linux Shell Script

How to merge two rows in a same row from a text file in linux shell script

You can use awk to merge lines together:

awk '
/^ +/{ # For lines starting with spaces,
gsub(/^ +/," "); # Replace these multiple spaces with only one
a=a $0; # Store the line into the variable a
next # Continue with the next line
}
{ # For lines not starting with spaces
$3=$3 a; # Append the variable a to the third element
a="" # Clear variable a
}
1 # Print the current line
' b.txt

How to combine two different rows by using awk sed or shell script

Since it is hard to determine which column the string belongs to, I make the following assumption:

  • The columns are perfectly aligned and space separated

so the following awk script will assume:

  • A line that does not start with a date will be merged into the next line
  • The width of the columns will be determined by the column-width of next line

note: if your file is aligned with blanks (a combination of tabs and spaces), we cannot make use of the field separator "\t" to distinguish fields as the number of tabs will depend on the field width.

Here is the tested script:

# If you have a tab-aligned file, replace all tabs by the
# correct sequence of spaces. In this example, we assume a single
# tab is equivalent to 8 spaces. Adopt if needed
{ gsub(/\t/," ",$0) }

# If the line does not start with a combination of numbers and hyphens
# it is a line that needs to be merged into the next line.
# store it and move to the next line
($1 !~ /^[-0-9]+$/) { tomerge=$0; next }

# If we picked up a tomerge line, try to figure out the fields
# by looking into the current line and determining the field widths.
(tomerge != "") {
# extract fields
n=1
for(i=1;i<NF;++i) {
m=index($0,$(i+1))
field[i]=substr(tomerge,n,m-n)
sub(/^[[:blank:]]*/,"",field[i]) # remove leading blanks
sub(/[[:blank:]]*$/,"",field[i]) # remove trailing blanks
n=m
}
field[NF]=substr(tomerge,n)
# perform merging
for(i=1;i<=NF;++i) $i= field[i] $i
# reset the tomerge value
tomerge=""
}
# print the line
{ $1=$1;print $0 }

which outputs:

$ awk -f script.awk file.txt
02-10-2018 11:50 linux-is-a-opensource user file
02-10-2018 11:46 linux-userfile user file1
02-10-2018 11:40 linux-userfile user-1user file2
02-10-2018 11:30 linux-linux-userfile user-2user file3

If you want it aligned, you can pass it to column -t as

$ awk -f script.awk file.txt | column -t

merge lines of a txt file using shell script

Here's one way using GNU sed:

sed ':a; N; $!ba; s/\\\n//g; s/\\$//' file

Another way using awk, may give you better performance:

awk '{ sub ("\\\\$", ""); printf "%s", $0 } END { print "" }' file

Results:

aaaaabbbbbccccc

Explanation:

The awk solution removes the trailing backslash (via substitution) and printf's each line (without a newline character). END (which is executed at the end of the script) then prints a newline character. This is superior to the sed solution, which creates a label called a and appends the next line of input into the pattern space. $!ba means 'if not at the last line of input, branch to label a'. The first substitution then removes each backslash and newline character from the pattern space. The second substitution removes the last, trailing backslash. This solution should be fast for small files, but probably won't be any faster than the awk for the same file. Although ... it was faster to write.

How to merge two files line by line in Bash

You can use paste:

paste file1.txt file2.txt > fileresults.txt

How to merge every two lines into one from the command line?

awk:

awk 'NR%2{printf "%s ",$0;next;}1' yourFile

note, there is an empty line at the end of output.

sed:

sed 'N;s/\n/ /' yourFile

How to concatenate multiple lines of output to one line?

Use tr '\n' ' ' to translate all newline characters to spaces:

$ grep pattern file | tr '\n' ' '

Note: grep reads files, cat concatenates files. Don't cat file | grep!

Edit:

tr can only handle single character translations. You could use awk to change the output record separator like:

$ grep pattern file | awk '{print}' ORS='" '

This would transform:

one
two
three

to:

one" two" three" 

Faster way to merge multiple files with unequal number of rows by column in bash

You could put all in one awk script:

awk -F'|' '{if (NR==FNR) a[$1]=$2; else print $1 "|" a[$1] " " $2}' a.txt b.txt 
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long

Bash to merge 2 consecutive lines in a file

Using sed:

sed '$!N;s/\n/,/' filename

Using paste:

paste -d, - - < filename

paste would leave a trailing , in case the input has an odd number of lines.

How to merge two files consistently line by line

You can use paste to format the files side by side:

$ paste -d" " file1.txt file2.txt
/etc/port1-192.9.200.1-255.555.255.0 /etc/port1-192.90.2.1-255.555.0.0
/etc/port2-192.9.200.1-255.555.255.0 /etc/port2-192.90.2.1-255.555.0.0
/etc/port3-192.9.200.1-255.555.255.0 /etc/port3-192.90.2.1-255.555.0.0
/etc/port4-192.9.200.1-255.555.255.0 /etc/port4-192.90.2.1-255.555.0.0
/etc/port5-192.9.200.1-255.555.255.0 /etc/port5-192.90.2.1-255.555.0.0

E.g.:

$ paste -d" " file1.txt file2.txt | while read from to; do echo mv "${from}" "${to}"; done
mv /etc/port1-192.9.200.1-255.555.255.0 /etc/port1-192.90.2.1-255.555.0.0
mv /etc/port2-192.9.200.1-255.555.255.0 /etc/port2-192.90.2.1-255.555.0.0
mv /etc/port3-192.9.200.1-255.555.255.0 /etc/port3-192.90.2.1-255.555.0.0
mv /etc/port4-192.9.200.1-255.555.255.0 /etc/port4-192.90.2.1-255.555.0.0
mv /etc/port5-192.9.200.1-255.555.255.0 /etc/port5-192.90.2.1-255.555.0.0

Of course you would want to throw in some safety checks ([ -f "${from}" ], ...).

Disclaimer: Works only if there are no spaces in your filenames.



Related Topics



Leave a reply



Submit