Skip to main content
added 430 characters in body
Source Link
heemayl
  • 58.1k
  • 9
  • 129
  • 144

If it were a string, i would do it using shell parameter expansion:

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

% echo "${str%%.*}"
211

You can still use a while construct and take each line into a variable and do this, but that would be slow for a large file. Also alternately you could use _. as the IFS and get the hardcoded field (like cut) instead if you want.


Example:

Example:

If it were a string, i would do it using shell parameter expansion:

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

% echo "${str%%.*}"
211

You can still use a while construct and take each line into a variable and do this, but that would be slow for a large file. Also alternately you could use _. as the IFS and get the hardcoded field (like cut) instead if you want.


Example:

Source Link
heemayl
  • 58.1k
  • 9
  • 129
  • 144

You would be better off using a standard text processing tool instead of a naive tool like cut.

Here are some ways:


With awk, getting the _ or . separated second last field:

awk -F '[_.]' '{print $(NF-1)}' file.txt

grep with PCRE (-P):

grep -Po '\d+(?=[^_]*$)' file.txt
  • -o only gets the matched portion

  • \d+ matches one or more digits

  • The zero width positive lookahead, (?=[^_]*$), ensures that no _ is following till end of the line


With sed:

sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
  • .*_ matches everything upto last _

  • ([[:digit:]]+) matches the required digits and put in captured group

  • .* matches the rest

  • In the replacement, only the captured group, \1, is used


With perl, same logic to the sed one:

perl -pe 's/.*_(\d+).*/$1/' file.txt 

If you must use cut, do it in two steps, first get the _ separated 4th field and then get . separated 1st field:

cut -d_ -f4 file.txt | cut -d. -f1

This is not recommended as this requires the field numbers to be hardcoded.


Example:

% cat file.txt                          
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg

% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222

% grep -Po '\d+(?=[^_]*$)' file.txt         
211
222

% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222

% perl -pe 's/.*_(\d+).*/$1/' file.txt 
211
222

% cut -d_ -f4 file.txt | cut -d. -f1
211
222