X3nion
X3nion

Reputation: 301

How can I avoid newlines after array elements when using readarray?

I've got a text file

Today, 12:34 
Today, 21:43 
Today, 12:43
https://123
https://456
https://789

and wanted to print each line into an array. Therefore I used:

readarray array <'file.txt'

Now I'd like to create a new array mixing date and the corresponding link, so in this case, line 1 corresponds with line 4 and so on. I wrote

declare -a array2
array2[0]=${array[0]}${array[3]}
array2[1]=${array[1]}${array[4]}
...

printing the whole array2 using "echo ${array2[*]}" gets the following:

Today, 12:34
https://123
 Today, 21:43
https://456
 Today, 12:43
https://789

Why are there newlines between the elements, so e.g. between array2[0] and array2[1] ? How could I get rid of them? And why is there an empty space before T in the second and the following lines? And is there a possibility to write the code above in a loop?

Kind regards, X3nion

Upvotes: 2

Views: 1012

Answers (3)

Ownture
Ownture

Reputation: 1

I found that simply using brace bracket syntax suffices to remove the line feed from a variable thusly:

foo_stripped=${foo_with_linefeed}

Simple and effective!

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84521

An awk solution would be much simpler (and much faster). Simply read all lines containing "Today" into an array in awk. Then beginning with the line not containing "Today" write the current line followed by the associated line from the array, e.g.

awk '/Today/{a[++n] = $0; next} {printf "%s\t%s\n", $0, a[++m]}' file.txt

Example Use/Output

With your example lines in file.txt, you would receive:

$ awk '/Today/{a[++n] = $0; next} {printf "%s\t%s\n", $0, a[++m]}' file.txt
https://123     Today, 12:34
https://456     Today, 21:43
https://789     Today, 12:43

Or if you wanted to change the order:

$ awk '/Today/{a[++n] = $0; next} {printf "%s\t%s\n", a[++m], $0}' file.txt
Today, 12:34    https://123
Today, 21:43    https://456
Today, 12:43    https://789

Addition Per-Comment

If you are receiving whitespace before the output with awk that is due to having whitespace before the first field. To eliminate the whitespace, you can force awk to recalculate each field, removing whitespace simply by setting a field equal to itself, e.g.

awk '{$1 = $1} /Today/{a[++n] = $0; next} {printf "%s\t%s\n", a[++m], $0}' file.txt

By setting the first field equal to itself ($1 = $1), you force awk to recalculate each field which would eliminate leading whitespace. Take for example your data with leading whitespace (each line is preceded by 3-spaces):

   Today, 12:34
   Today, 21:43
   Today, 12:43
   https://123
   https://456
   https://789

Using the updated command gives the answers shown above with the whitespace removed.

Using paste

You can use the paste command as another option along with the wc -l (word count lines) command. Simply determined the number of lines and then use process substitution to output the first 1/2 of the lines followed by the last 1/2 of the lines and combine them with paste, e.g.

$ lc=$(wc -l <file.txt); paste <(head -n $((lc/2)) file.txt) <(tail -n $((lc/2)) file.txt)
Today, 12:34    https://123
Today, 21:43    https://456
Today, 12:43    https://789

(above, lc holds the line-count and then head and tail are used to split the file) Let me know if you have questions or if this isn't what you were attempting to do.

Upvotes: 1

Charles Duffy
Charles Duffy

Reputation: 295291

Use the -t argument to prevent the newlines from being included in the data stored in the individual array elements:

readarray -t array <file.txt

BTW, you can always strip your newlines after-the-fact, even if you don't prevent them from being read in the first place, by using the ${var%suffix} parameter expansion with the $'\n' syntax to refer to a newline literal:

array2[0]=${array[0]%$'\n'}${array[3]%$'\n'}

Upvotes: 5

Related Questions