How to swap the first line with last line in a text file using SED/AWK

点点圈 提交于 2020-06-15 05:50:44

问题


I am trying to swap the first line with last line in a text file in unix file has:

line1
line2
line3
line4
line5
line6

I want like this:

line6 
line2
line3
line4
line5
line1

I am using sed -n -e '1 s/^.*$/$p' file . Which is not happening.


回答1:


EDIT2: As per Ed sir's comment adding this solution too here which will be more suitable in case 2nd line is empty then also it will work.

awk 'NR==1{first=$0;next} NR>2{val=val prev ORS} {prev=$0} END{print prev ORS val first}  Input_file

EDIT: To exchange only first and last line following may help you(considering that your Input_file is same as shown sample).

awk 'FNR==1{first=$0;next} {val=(val?val ORS prev:prev?$0:"")} {prev=$0} END{print $0 ORS val ORS first}' Input_file

Explanation:

awk '
FNR==1{                            ##Checking if line is first line then do following.
  first=$0;                        ##Creating varable first whose value is current line value.
  next                             ##next will skip all further statements from here.
}
{
  val=(val?val ORS prev:prev?$0:"")  ##Creating variable named val here whoe value is concatenating to its own value with variable prev value.
}
{
  prev=$0                          ##Creating variable prev whose value will be current value of line but will become previous value for next line.
}
END{
  print $0 ORS val ORS first       ##Printing current line ORS val ORS and first here.
}'  Input_file                     ##Mentioning Input_file name here.

Could you please try following and let me know if this helps you.

awk -v from=1 -v to=6 'FNR==from{source=$0;next} FNR==to{target=$0;next} {val=val?val ORS $0:$0} END{print target ORS val ORS source}' Input_file



回答2:


This might work for you (GNU sed):

sed 'H;$!d;x;s/\n\([^\n]*\)\(\n.*\n\)\(.*\)/\3\2\1/' file

Copy the whole file into the hold space (HS) and after the last line, swap to the HS, split the file into first line, middle and last line and substitute the first and last lines.

A two pass alternative solution:

sed -n '1s/.*/$c&/p;$s/.*/1c&/p' file | sed -f - file

Create a sed script to change the first line to the last and last line to the first.

Another solution using cat, head, tail and sed:

cat <(tail -1 file) <(sed '1d;$d' file) <(head -1 file)

Another sed solution:

sed -E '1h;1d;:a;N;$!ba;s/(.*)\n(.*)/\2\n\1/;G' file



回答3:


In sed, you'll need to make two passes; it probably makes more sense to use ed instead. Then we just need two move commands - move the last line to just after line 1, then move the first line to the end:

$m1
1m$

Demo

#!/bin/bash

set -euo pipefail

# Create our input file

file=$(mktemp)
trap 'rm "$file"' EXIT

cat >"$file" <<END
line1
line2
line3
line4
line5
line6
END

echo Before:
cat "$file"
echo

# Make the change

ed -s "$file"  <<<$'$m1\n1m$\nwq'

# Show the result

echo After:
cat "$file"

If you need to write a different output file, you can of course add a filename argument to the wq command, as usual.




回答4:


Just in case a oneliner mixing, head, tail and sed:

$ FIRST=$(head -1 file.txt) LAST=$(tail -1 file.txt) \
sed "1 s/^.*$/${LAST}/" file.txt | sed "$ s/^.*$/${FIRST}/"



回答5:


For very large files, you might be interested in a double pass:

awk '(NR!=FNR){print (FNR==1 ? t : (FNR==c ? h : $0) ); next }
     (NR==1){h=$0}{t=$0;c=NR}' file file



回答6:


Using the sponge util:

f=file
{ tail -1 $f ; tail -n +2 $f | head -n -1 ; head -1 $f ; } | sponge $f


来源:https://stackoverflow.com/questions/51440378/how-to-swap-the-first-line-with-last-line-in-a-text-file-using-sed-awk

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!