Reputation: 43
In the incoming string stream from the standard input, swap the even and odd lines.
I've tried to do it like this, but reading from file and $i -lt $a.count
aren't working:
$a= gc test.txt
for($i=0;$i -lt $a.count;$i++)
{
if($i%2)
{
$a[$i-1]
}
else
{
$a[$i+1]
}
}
Please, help me to get this working
Upvotes: 1
Views: 659
Reputation: 8134
There's already a good awk
-based answer to the question here, and there are a few decent-looking sed
and awk
solutions in Swap every 2 lines in a file. However, the shell solution in Swap every 2 lines in a file is almost comically incompetent. The code below is an attempt at a functionally correct pure Bash solution. Bash is very slow, so it is practical to use only on small files (maybe up to 10 thousand lines).
#! /bin/bash -p
idx=0 lines=()
while IFS= read -r 'lines[idx]' || [[ -n ${lines[idx]} ]]; do
(( idx == 1 )) && printf '%s\n%s\n' "${lines[1]}" "${lines[0]}"
idx=$(( (idx+1)%2 ))
done
(( idx == 1 )) && printf '%s\n' "${lines[0]}"
lines
array is used to hold two consecutive lines.IFS=
prevents whitespace being stripped as lines are read.idx
variable cycles through 0, 1, 0, 1, ...
(idx=$(( (idx+1)%2 ))
) so reading to lines[idx]
cycles through putting input lines at indexes 0
and 1
in the lines
array.read
function returns non-zero status immediately if it encounters an unterminated final line in the input. That could cause the loop to terminate before processing the last line, thus losing it in the output. The || [[ -n ${lines[idx]} ]]
avoids that by checking if the read
actually read some input. (Fortunately, there's no such thing as an unterminated empty line at the end of a file.)printf
is used instead of echo
to output the lines because echo
doesn't work reliably for arbitrary strings. (For instance, a line containing just -n
would get lost completely by echo "$line"
.) See Why is printf better than echo?.(( idx == 1 )) && printf '%s\n' "${lines[0]}"
) just passes the last line through, after the swapped lines. Other reasonable options would be to drop the last line or print it preceded by an extra blank line. The code can easily be modified to do one of those if desired.Upvotes: 0
Reputation: 4890
Suggesting one line awk
script:
awk '!(NR%2){print$0;print r}NR%2{r=$0}' input.txt
awk
script explanation!(NR % 2){ # if row number divide by 2 witout reminder
print $0; # print current row
print evenRow; # print saved row
}
(NR % 2){ # if row number divided by 2 with reminder
evenRow = $0; # save current row in variable
}
Upvotes: 2