Linux cut last character

Delete the last character of a string using string manipulation in shell script

Notice that for older bash ( for example, bash 3.2.5 on OS X), you should leave spaces between and after colons:

This works for bash version 4.2-alpha and above, too bad the version I have access to is earlier. :-/

@iamaziz: From bash changelog, the negative length in $ was added only in bash 4.2 . Maybe OSX add its own patch for bash .

In a POSIX shell, the syntax $ means something different — it expands to the value of t if t is set and non null, and otherwise to the value 2 . To trim a single character by parameter expansion, the syntax you probably want is $

Note that in ksh93 , bash or zsh , $ or $ (note the space) are legal as a substring expansion but are probably not what you want, since they return the substring starting at a position 2 characters in from the end (i.e. it removes the first character i of the string ijk ).

See the Shell Parameter Expansion section of the Bash Reference Manual for more info:

@afraisse $ removes the shortest suffix pattern matching word — see the Parameter Expansion section of man bash

Using sed it should be as fast as

Your single echo is then echo ljk | sed ‘s/.$//’ .
Using this, the 1-line string could be any size.

Note that in the general case, it doesn’t delete the last character of the string, but the last character of every line of the string.

Yes, \n is a character, @LuisA.Florit 🙂 You can amend the regex easily if you know more about your input, for example /.\n$/\n/ in your case to keep the last newline and remove the character before the last newline. I think even /.\n?$/\n/ might be an option to ensure a new line at the end of stream.

for removing the last n characters from a line that makes no use of sed OR awk :

> echo lkj | rev | cut -c (n+1)- | rev 

so for example you can delete the last character one character using this:

> echo lkj | rev | cut -c 2- | rev > lk 

DESCRIPTION
The rev utility copies the specified files to the standard output, reversing the order of characters in every line. If no files are speci- fied, the standard input is read.

if you don’t know the length of the string, try:

A few options depending on the shell:

  • POSIX: t=$
  • Bourne: t=`expr » $t» : ‘ \(.*\).’`
  • zsh/yash: t=$
  • bash/zsh: t=$
  • ksh93/bash/zsh/mksh: t=$-1>
  • ksh93/bash/zsh/mksh: t=$
  • ksh93: t=$
  • es: @ ~~ $t *?
Читайте также:  Лучшие инструменты kali linux

Note that while all are supposed to strip the last character, you’ll find that some implementations (those that don’t support multi-byte characters) strip the last byte instead (so would likely corrupt the last character if it was multi-byte).

The expr variant assumes $t doesn’t end in more than one newline character. It will also return a non-zero exit status if the resulting string ends up being 0 (or 000 or even -0 with some implementations). It could also give unexpected results if the string contains invalid characters.

Nice and thorough! But. I assume all of those shells support POSIX, so everyone should just use that one to be the most portable. Smallest character count, too!

@Russ, t=$ is not Bourne but you’re not likely to come across a Bourne shell nowadays. $ does work in all the other ones though.

@rien333. I’d wait for the interface to stabilize a bit. fish is work in progress. 2.3.0 which introduced the string builtin was not released at the time of the Q&A. With the version I’m testing it on, you need string replace -r ‘(?s).\z’ » — $t (and I’d expect they’d want to change that, they should change the flags they pass to PCRE) or more convoluted ones. It also deals poorly with newline characters, and I know they’re planning on changing that as well.

@Timo, not sure what you mean. None of the solutions I gave are bash-specific. The only one invented by bash AFAIK is t=$ (extending the $ ksh93 operator). For each, I gave which shells support it. You can use the Bourne/POSIX ones from and modern sh .

The most portable, and shortest, answer is almost certainly:

This works in bash, sh, ash, dash, busybox/ash, zsh, ksh, etc.

It works by using old-school shell parameter expansion. Specifically, the % specifies to remove the smallest matching suffix of parameter t that matches the glob pattern ? (ie: any character).

See «Remove Smallest Suffix Pattern» here for a (much) more detailed explanation and more background. Also see the docs for your shell (eg: man bash ) under «parameter expansion».

As a side note, if you wanted to remove the first character instead, you would use $ , since # matches from the front of the string (prefix) instead of the back (suffix).

Also worth noting is that both % and # have %% and ## versions, which match the longest version of the given pattern instead of the shortest. Both $ and $ would do the same as their single operator in this case, though (so don’t add the useless extra character). This is because the given ? pattern only matches a single character. Mix in a * with some non-wildcards and things get more interesting with %% and ## .

Читайте также:  Wine linux установка настройка

Understanding parameter expansions, or at least knowing about their existence and knowing how to look them up, is incredibly useful for writing and deciphering shell scripts of many flavors. Parameter expansions often look like arcane shell voodoo to many people because. well. they are arcane shell voodoo (although pretty well documented if you know to look for «parameter expansion»). Definitely good to have in the tool belt when you’re stuck in a shell, though.

Источник

How can I remove the last character of a file in unix?

How can I remove only the last character (the e, not the newline or null) of the file without making the text file invalid?

Listing a bunch of garbage sed and awk commands that strip the last character off of every line didn’t feel terribly constructive. Heh, knew I was going to get dinged for that one. Still, couldn’t bring myself to leave in the sentence «I tried a bunch of sed and awk, but could only strip out every line’s last char in a variety of ways».

9 Answers 9

A simpler approach (outputs to stdout, doesn’t update the input file):

  • $ is a Sed address that matches the last input line only, thus causing the following function call ( s/.$// ) to be executed on the last line only.
  • s/.$// replaces the last character on the (in this case last) line with an empty string; i.e., effectively removes the last char. (before the newline) on the line.
    . matches any character on the line, and following it with $ anchors the match to the end of the line; note how the use of $ in this regular expression is conceptually related, but technically distinct from the previous use of $ as a Sed address.
  • Example with stdin input (assumes Bash, Ksh, or Zsh):

To update the input file too (do not use if the input file is a symlink):

  • On macOS, you’d have to use -i » instead of just -i ; for an overview of the pitfalls associated with -i , see the bottom half of this answer.
  • If you need to process very large input files and/or performance / disk usage are a concern and you’re using GNU utilities (Linux), see ImHere’s helpful answer.

Removes one (-1) character from the end of the same file. Exactly as a >> will append to the same file.

The problem with this approach is that it doesn’t retain a trailing newline if it existed.

if [ -n "$(tail -c1 file)" ] # if the file has not a trailing new line. then truncate -s-1 file # remove one char as the question request. else truncate -s-2 file # remove the last two characters echo "" >> file # add the trailing new line back fi 

This works because tail takes the last byte (not char).

Читайте также:  Check public ip on linux

It takes almost no time even with big files.

Why not sed

The problem with a sed solution like sed ‘$ s/.$//’ file is that it reads the whole file first (taking a long time with large files), then you need a temporary file (of the same size as the original):

sed '$ s/.$//' file > tempfile rm file; mv tempfile file 

And then move the tempfile to replace the file.

Источник

Remove last character from line

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).

@jasonwryan, unfortunately, there are a lot of awk implementations where that doesn’t work, where the + unary operator is just ignored and doesn’t force conversion of strings to numerical.

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:

  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)

In awk, you could do one of

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 

Источник

Оцените статью
Adblock
detector