101

I want to remove last character from a line:

[root@ozzesh ~]#df -h | awk  '{ print $5 }'
Use%
22%
1%
1%
59%
51%
63%
5%

Expected result:

Use
22
1
1
59
51
63
5
Braiam
  • 35,991
Özzesh
  • 3,669

11 Answers11

151
sed 's/.$//'

To remove the last character.

But in this specific case, you could also do:

df -P | awk 'NR > 1 {print $5+0}'

With the arithmetic expression ($5+0) we force awk to interpret the 5th field as a number, and anything after the number will be ignored.

Note that GNU df (your -h is already a GNU extension, though not needed here) can also be told to only output the disk usage percentage:

df --output=pcent | tail -n +2 | tr -cd '0-9\n'

(tail skips the headers and tr removes everything but the digits and the line delimiters).

On Linux, see also:

findmnt -no USE%
32

With sed, this is pretty easy:

$ cat file
Use%
22%
1%
1%
59%
51%
63%
5%
$ sed 's/.$//' file
Use
22
1
1
59
51
63
5

The syntax is s(ubstitute)/search/replacestring/. The . indicates any character, and the $ the end of the line. So .$ will remove the last character only.

In this case, your complete command would look:

df -h | awk '{ print $5}' | sed 's/.$//'
Bernhard
  • 12,272
26

I have two solutions :

  1. cut: echo "somestring1" | rev | cut -c 2- | rev

    Here you reverse the string and cut the string from 2nd character and reverse again.

  2. sed : echo "somestring1" | sed 's/.$//'

    Here you will search for regular expression .$ which means any characters followed by a last character and replace it with null // (between the two slashes)

Jakuje
  • 21,357
Guru
  • 411
  • 5
  • 4
11

In awk, you could do one of

awk '{sub(/%$/,"",$5); print $5}'
awk '{print substr($5, 1, length($5)-1)}'
glenn jackman
  • 85,964
7

Did you know that head and tail can work on a character basis instead of per line?

$ printf "I don't like periods." | head -c-1
I don't like periods

(BTW, printf is used here to prevent printing the "new line" character at the end of the line. If your output has a new line character and you want to remove that as well as the last non-whitespace character, use head -c-2).

This is basically the same as "Guru"'s solution using cut, but without the funky rev back and forth that they need to use because cut has no syntax for "last n things".

To iterate over a stream of lines and remove the last character of each, one might do something like this:

some-command | while read line; do echo $(head -c-2 <<<"$line"); done
Guss
  • 12,628
  • 2
    This will remove the last character of a file, not the last character of every line. – thanasisp Dec 15 '20 at 18:25
  • Got it, easy to fix. gimme a minute... – Guss Dec 15 '20 at 18:46
  • should we do && echo "" in order to get rid of EOF char that might be printed out – alper Mar 13 '21 at 15:31
  • @alper - when you say "get rid of EOF" you mean "add missing EOL"? If so, and you mean in the first example, then yes - echo "" prints out an zero-length string, after which the echo implementation auto-adds \n (which the printf in my example didn't on purpose, as is explained in the BTW). – Guss Mar 14 '21 at 08:57
  • @alper - that being said, if you want to mimic the auto-newline echo behavior, I prefer to use it by having echo actually print the entire thing - as I demonstrated in the second example. – Guss Mar 14 '21 at 08:58
  • @Guss I don't know the term but I keep seeing a character (%) so when I do echo "" that character is gone – alper Mar 18 '21 at 17:39
4
df -h | awk 'NR > 1{ print $5 }' | cut -d "%" -f1
phk
  • 5,953
  • 7
  • 42
  • 71
  • 1
    This answer could be more helpful to others beyond OP if you could provide a bit of explanation regarding how it works and possibly why this might be better than the alternatives – Fox Apr 01 '17 at 20:09
  • Welcome to Unix Stackexchange! You can take the tour to get a feel for how this site works. When giving an answer it is preferable to give some explanation as to WHY your answer is the one the reader wants. This means it is best if you give some explanation of how it works. If you look above, you will see that all of the highly voted answers explain the code. – Stephen Rauch Apr 01 '17 at 20:10
  • Upvoted for the use of cut -d '%' -f1 which is the correct answer to get everything in the line up to the first '%'. – Titou Dec 10 '18 at 10:36
  • Plus I believe only harmful / wrong answers should ever get downvoted below 0. – Titou Dec 10 '18 at 10:38
4
echo "123" | perl -ple 'chop'
12
bsb
  • 141
2

another approach:

mapfile -t list < <(df -h)
printf '%s\n' "${list[@]%?}"

Turn it into a function:

remove_last() {
  local char=${1:-?}; shift
  mapfile -t list < <("$@")
  printf '%s\n' "${list[@]%$char}"
}

Then call it like this:

remove_last '%' df -h

mapfile is a bash4 feature.

The catch here is that you must supply a character to remove; if you want it to just be whatever the last character happens to be then you must pass '?' or ''. quotes required.

1
$ df -h | awk '{print $5}' | cut -d '%' -f1 
Rahul
  • 13,589
ashok
  • 11
1

Try with this:

df -h | awk  '{ print $5 }' | sed "s/%//"

The normal use is: (ie)

VALUE=987654321
echo X123456789X | sed "s/123456789/${VALUE}/"

Response should be: X987654321X

Chuss
  • 111
0
sed -ie '$d' filename

here -i is to write changes
      e means expression
      $ means last line
      d means delete

Note:Without -e option $ wont work

Optional: To delete 1st and last line use sed -ie '1d;$d' filename