Removing the new line in the last line of a text file using sed - text

I wanna remove the new line in the last line of my text file using sed. For example the input is like the following:
1
1
1
1
1
1
And I want to have an output like this without any new lines at the end of the text file:
1
1
1
1
1
1

This might work for you (GNU sed):
sed -z 's/\n\+$//' file
This will remove a newline(s) at the end of a file provided there are no null characters.
N.B. Normal use of sed i.e. without the -z option which slurps the file into memory, will remove any newlines before the sed commands can act on them.

Using sed
sed '/^$/d' input_file
This will remove all empty lines

Starting with some test data:
$ printf "%s\n" {a..e} "" "" | cat -n
1 a
2 b
3 c
4 d
5 e
6
7
I would approach the problem like this: reverse the file, remove blank lines
at the top, then re-reverse the file
$ printf "%s\n" {a..e} "" "" | tac | awk 'NF && !p {p=1}; p' | tac | cat -n
1 a
2 b
3 c
4 d
5 e
NF is the awk variable for "number of fields in this record". p is a variable I'm using to indicate when to start printing. The first time that NF is non-zero, we set the p variable to a true value. The standalone p at the end triggers the default action to print the record.
Removing the newline on the last line is a different story.
Given this file:
$ cat > file
first
second
third
$ od -c file
0000000 f i r s t \n s e c o n d \n t h i
0000020 r d \n
0000023
We can use perl:
$ perl -i -0777 -ne 's/\n+$//; print' file
$ od -c file
0000000 f i r s t \n s e c o n d \n t h i
0000020 r d
0000022
or tr to translate newlines to some other character, and sed to remove the trailing character
$ tr '\n' '\034' < file | sed $'s/\034$//' | tr '\034' '\n' | od -c
0000000 f i r s t \n s e c o n d \n t h i
0000020 r d
0000022

Related

Why does wc count one extra character in my file? [duplicate]

This question already has an answer here:
wc -m in unix adds one character
(1 answer)
Closed 6 years ago.
1.) I am using Debian 8.4 on a virtual box and as I ran the command wc sample.txt to sample.txt containing:
Hello
The output to the command was
1 1 6 sample.txt
Is the extra character EOF? If it is then how come when I ran the same command for an empty file the output was..
0 0 0 sample.txt
You have a trailing new line and this is what wc reports.
See for example if we create a file with printf:
$ printf "hello" > a
$ cat a | hexdump -c
0000000 h e l l o
0000005
$ wc a
0 1 5 a
However, if we write with something like echo, a trailing new line is appended:
$ echo "hello" > a
$ cat a | hexdump -c
0000000 h e l l o \n
0000006
$ wc a
1 1 6 a

How to get a single output file with N lines from N multiline files?

I am looking for some effective way to concatenate multiple multiline files into one file - here is an example for three input files:
1.txt:
a b
c d
2.txt:
e f
g
h
3.txt:
ijklmn
output.txt:
a b c d
e f g h
ijklmn
(Replacing each linebreak with single whitespace). Which way can you recommend?
Using BASH for loop:
for i in [0-9]*.txt; do tr '\n' ' ' < "$i"; echo; done > output.txt
cat output.txt
a b c d
e f g h
ijklmn
If you want to strip one ending space before each line break then use:
for i in [0-9]*.txt; do tr '\n' ' ' < "$i"; echo; done | sed 's/ *$//' > output.txt

calculate count of char use in string

I'm trying to make this program work and I can't, The script i want must should calculate count of char use in string
example :
string=good
result=g1o2d1
is there any way to write script that calculate exactly count of string like my example or not ?
#!/bin/bash
string=ssstttrrrriiiinnnnngg
z=$( for((i=0;i<${#string};i++)) do; echo ${string:i:1}; done | uniq -c )
echo $z
my result :
s 3 t 3 r 4 i 4 n 5 g 2
but for analysis some document i want script to calculate char some like
firstchar1=$( bash script )
......
i need that value for use another script
please advise me
regards
$ echo "abaaacdefg" | grep -o .
a
b
a
a
a
c
d
e
f
g
$ echo "abaaacdefg" | grep -o .| sort
a
a
a
a
b
c
d
e
f
g
$ echo "abaaacdefg" | grep -o .| sort | uniq -c
4 a
1 b
1 c
1 d
1 e
1 f
1 g
$ echo "abaaacdefg" | grep -o .| sort | uniq -c | awk '{printf $2$1}'
a4b1c1d1e1f1g1
See
Bash: Split string into character array and
counting duplicates in a sorted sequence using command line tools

Making horizontal String vertical shell or awk

I have a string
ABCDEFGHIJ
I would like it to print.
A
B
C
D
E
F
G
H
I
J
ie horizontal, no editing between characters to vertical. Bonus points for how to put a number next to each one with a single line. It'd be nice if this were an awk or shell script, but I am open to learning new things. :) Thanks!
If you just want to convert a string to one-char-per-line, you just need to tell awk that each input character is a separate field and that each output field should be separated by a newline and then recompile each record by assigning a field to itself:
awk -v FS= -v OFS='\n' '{$1=$1}1'
e.g.:
$ echo "ABCDEFGHIJ" | awk -v FS= -v OFS='\n' '{$1=$1}1'
A
B
C
D
E
F
G
H
I
J
and if you want field numbers next to each character, see #Kent's solution or pipe to cat -n.
The sed solution you posted is non-portable and will fail with some seds on some OSs, and it will add an undesirable blank line to the end of your sed output which will then become a trailing line number after your pipe to cat -n so it's not a good alternative. You should accept #Kent's answer.
awk one-liner:
awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++)print i,$i}'
test :
kent$ echo "ABCDEF"|awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++)print i,$i}'
1 A
2 B
3 C
4 D
5 E
6 F
So I figured this one out on my own with sed.
sed 's/./&\n/g' horiz.txt > vert.txt
One more awk
echo "ABCDEFGHIJ" | awk '{gsub(/./,"&\n")}1'
A
B
C
D
E
F
G
H
I
J
This might work for you (GNU sed):
sed 's/\B/\n/g' <<<ABCDEFGHIJ
for line numbers:
sed 's/\B/\n/g' <<<ABCDEFGHIJ | sed = | sed 'N;y/\n/ /'
or:
sed 's/\B/\n/g' <<<ABCDEFGHIJ | cat -n

How to duplicate lines in Linux with keeping the original order?

I have a file (with only 1 column) like this:
A
B
Z
D
N
and what I want to do is to duplicate each line so I get this:
A
A
B
B
Z
Z
D
D
N
N
I only could think of using cat for the same file and then sort it:
cat file1 file1 | sort -k1 > file1_duplicate
but then I lose the order of my file which is important for me:
A
A
B
B
D
D
N
N
Z
Z
any suggestion would be helpful.
Try e.g.
sed p file >newfile
awk '{print $1;}{print $1;}' file.txt > duplicatefile.txt
LSB has perl5. This will do the trick:
cat file1 | perl -pe '$_.=$_' > file1_duplicate
With coreutils paste you can do it like this:
paste -d'\n' file file
cat file | tail --lines=1 >> file

Resources