2

I would like to remove the 4 chars before the last char.

Input:

abc2a982
e1kei9e5bc5
e1edeaww58476

Expected output:

abc2
e1kei95
e1edeaww6

So far I have tried:

cat file | while read line; do echo $line | sed 's/.\{4}$\1/';done

I guess there should be something else instead of \1.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
achille
  • 113
  • 8
  • Possible duplicate of [How can I strip first X characters from string using sed?](https://stackoverflow.com/questions/11469989/how-can-i-strip-first-x-characters-from-string-using-sed) – l'L'l Dec 21 '17 at 18:31

2 Answers2

4
% cat input | sed 's/....\(.\)$/\1/'
abc2
e1kei95
e1edeaww6
Inian
  • 80,270
  • 14
  • 142
  • 161
Gambit Support
  • 1,432
  • 1
  • 7
  • 17
  • LOL, unless "cat input" is a placeholder for a much more complicated pipeline. – Gambit Support Dec 21 '17 at 18:33
  • Actually I tried this solution, but my error was that I put '\\(.\\)' for all '.' but the first. – achille Dec 21 '17 at 18:43
  • @achille - that wasn't included in your question, but it should still work. You could just count the parenthesized expressions, and select the one you want to place in your replacement string. `'s/....\(.\)$/\1/'` is functionally equivalent to `'s/\(.\)\(.\)\(.\)\(.\)\(.\)$/\5/'`. – ghoti Dec 21 '17 at 18:47
0

If you had the urge to do this with bash alone, and avoid using sed, you could use parameter expansion to manipulate your strings.

while read -r line; do
  allbutlast1="${line%?}"          # strip the last character from $line
  lastchar="${line#$allbutlast1}"  # strip what we just captured from start of line
  allbutlast5="${line%?????}"      # strip the last 5 characters
  printf '%s%s\n' "$allbutlast5" "$lastchar"
done

Or if you're using bash as your shell, you have additional options:

while read -r line; do
  printf '%s%s\n' "${line:0:$(( ${#line} - 5))}" "${line:$(( ${#line} - 1 ))}"
done

(bash code compacted to save on throw-away variables.)

The POSIX code (first example) uses parameter expansions ${var%...} and ${var#...} to construct the output. The Bash code uses ${var:start:length} notation, with arithmetic expansion, $(( ... )).

This answer is included mostly for academic purposes. You'll get better performance using awk or sed than processing input line by line with a shell script.

Speaking of which, an awk solution might mirror the bash solution:

awk '{print substr($0,1,length($0)-5) substr($0,length($0))}'

Note that while bash's ${var:start:length} notation starts numbering characters at zero, awk's substr() function starts at one.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
ghoti
  • 45,319
  • 8
  • 65
  • 104