How to Find Certain Character Position in Shell

How to find certain character position in shell

Using BASH:

a="This is test.txt file"
s="${a%%.*}" # remove all text after DOT and store in variable s
echo "$(( ${#s} + 1 ))" # get string length of $s + 1

13

Or using awk:

awk -F. '{print length($1)+1}' <<< "$a"
13

Search for specific characters in specific positions of line

To search for "foo" at position 42:

egrep '^.{42}foo'

You can run a command like this multiple times on your input:

egrep '^.{42}foo' inputfile.txt > lineswithfoo.txt
egrep '^.{42}bar' inputfile.txt > lineswithbar.txt
...

or as a loop:

for pattern in foo bar qux; do
egrep "^.{42}$pattern" inputfile.txt > lineswith$pattern.txt
done

How can I get a character of a string at a particular index?

The following script loops through all of the digits in the input string and adds them together:

#!/bin/bash

s="$1"

for ((i=0; i<${#s}; ++i)); do
((t+=${s:i:1}))
done

echo "sum of digits: $t"

The syntax ${s:i:1} extracts a substring of length 1 from position i in the string $s.

Output:

$ ./add.sh 963
sum of digits: 18

If you wanted to continue adding together the digits until there was only one remaining, you could do this instead:

#!/bin/bash

s="$1"

while (( ${#s} > 1 )); do
t=0
for ((i=0; i<${#s}; ++i)); do
((t+=${s:i:1}))
done
echo "iteration $((++n)): $t"
s=$t
done
echo "final result: $s"

The outer while loop continues as long as the length of the string is greater than 1. The inner for loop adds together each digit in the string.

Output:

$ ./add.sh 963
iteration 1: 18
iteration 2: 9
final result: 9

Not that you asked for it but there are many ways to sum all of the digits in a string. Here's another one using Perl:

$ perl -MList::Util=sum -F -anE 'say sum @F' <<<639
18

List::Util is a core module in Perl. The sum subroutine does a reduction sum on a list to produce a single value. -a enables auto-split mode so the input is split into the array @F. -F is used to set the field delimiter (in this case it is blank, so every character counts as a separate field). -n processes every line of input one at a time and -E is used to enter a Perl one-liner but with newer features (such as say) enabled. say is like print but a newline is added to the output.

If you're not familiar with the <<< syntax, it is equivalent to echo 639 | perl ....

Cut string from position to character

If you want to stick with cut then this might be what you want:

echo 'Export text H8X7IS5G.FIC NB regs COLOLO 4138/4138' |
cut -c41- | cut -d/ -f1

There are many other ways to accomplish this task. If you have a grep which supports perl-compatible regular expressions, for instance, then I'd suggest something along this line:

grep -Po '.{40}\K[^/]*'

Or, a sed one-liner:

sed 's/.\{40\}//; s|/.*||'

Or, using pure bash

[[ $line =~ .{40}([^/]*) ]] && printf '%s\n' "${BASH_REMATCH[1]}"

Using sed command in shell script for substring and replace position to need

If you want to put the quotes in, I'd still use awk.

$: awk -F'|' 'BEGIN{q="\047"} {print  q $1 q","q substr($2,17,14) q","q $3 q","q $4 q"\n"}' <<< "X|001200000000000000000098765432|1234567890|TQ"
'X','00000098765432','1234567890','TQ'

If you just want to use sed, note that you say above you want to remove 16 characters, but you are actually only removing 14.

$: sed -E "s/^(.)[|].{14}([^|]+)[|]([^|]+)[|]([^|]+)/'\1','\2','\3','\4'/" <<< "X|0012000000000000000098765432|1234567890|TQ"
'X','00000098765432','1234567890','TQ'

Search Unix file name by positions of the characters in file name

Bash globbing has more than just *, e.g. ?, which means "any single character":

$ ls -1 ABC*C
ABC2019120601C
ABC2019120611C
$ ls -1 ABC????????0??
ABC2019120601C
$ ls -1 ABC????????1??
ABC2019120611C

Cut characters from position from string in bash

Agree with the answer by Charles Duffy. If you know you want specifically "JAC" instead of what indices you want removed, you could do:

str="S202SCTRXBAVCWPJAC001181204120000.N"
echo "${str/JAC/}"


Related Topics



Leave a reply



Submit