3

I am using a Mac terminal (bash) and I have a file called data_list.txt that contains n lines as follows:

aaabbbccc_7777.txt 
nnhhaa_8888.txt 
ayquabay_9999.txt 
ayqynbnbn_1122.txt 
ooppaa_3454.txt

How can I remove the last 8 characters of each line?

Expected output of data_list.txt:

aaabbbccc_ 
nnhhaa_ 
ayquabay_ 
ayqynbnbn_ 
ooppaa_

Thanks for any help

2
  • 1
    Are the spaces part of the input?
    – choroba
    Commented Oct 22, 2021 at 8:35
  • 1
    Please specify if you want to get rid of whatever is after last 'underline' char... If that is the case, the better script would be: sed 's/\(.*_\).*$/\1/' data_list.txt. This will work even if you have multiple underlines '_' in one line, because sed is 'gready'.
    – Damir
    Commented Oct 22, 2021 at 8:43

5 Answers 5

9

If you want to delete the last 8 characters, or all of them if there are fewer than 8, you could do:

sed "s/.\{0,8\}$//; /^$/d" data_list.txt

No need for extended regex. This will clear as many characters as it can, but no more than 8. If that leaves an empty line, it'll be removed from the output.

If you need to clear any trailing whitespace (without including it in the 8 characters), you could do:

sed "s/.\{0,8\}[[:space:]]*$//" data_list.txt

I can only guess what the actual condition is for what should be removed at the end (e.g., everything after the underscore, or a number + the extension), but if you want to strip the file extension and any digits before it:

sed "s/[[:digit:]]*\..*$//" data_list.txt

Other answers have already shown how to remove everything after the underscore, so I won't repeat that.

0
5

To your exact input (all the lines at their ends have white space, except last line) you can use this (I suppose you want get rid of 'after _ part':

sed 's/........ *$//' data_list.txt

For getting rid of anything after last 'underline' character use this one:

sed 's/\(.*_\).*$/\1/' data_list.txt

It will also work on lines that have multiple 'underline' characters, because sed is 'greedy'. Although I don't not know if this will work on MacOS, at least this will be useful for feauture Linux sed users that google search engine will land here...

2
  • I see no reason why this should not work on MacOS. But future sed users could learn from an explanation of your second command and why you did not use s/_[^_]*$/_/ instead.
    – Philippos
    Commented Oct 22, 2021 at 9:53
  • Technically, the trailing space you are also trimming would usually also count as characters but the OP seems to agree this is correct.
    – Ned64
    Commented Oct 22, 2021 at 10:52
3

Here's an awk solution that's just as fast as frippe's sed approach, using an example file with 100,000 lines:

time awk '{print substr($0, 1, length($0)-8)}' 100k.txt

real    0m4.110s
user    0m0.142s
sys     0m0.422s

time sed "s/.\{0,8\}$//; /^$/d" 100k.txt

real    0m4.043s
user    0m1.558s
sys     0m0.345s

Replace 8 with any number. The main difference here is that awk will print a newline if your trim length exceeds your line length, whereas sed will not.

2

I found a solution with sed (note that this is for MacOS):

sed -i '' 's/.\{8\}$//' data_list.txt
0
1

Using Raku (formerly known as Perl_6)

raku -ne '.trim-trailing.chop(8).put;'

OR

raku -pe '.=trim-trailing; .=chop(8);'

Sample Input:

wxxyyyzzzz_1234.txt
aaabbbccc_7777.txt 
nnhhaa_8888.txt 
ayquabay_9999.txt 
ayqynbnbn_1122.txt 
ooppaa_3454.txt

Sample Output:

wxxyyyzzzz_
aaabbbccc_
nnhhaa_
ayquabay_
ayqynbnbn_
ooppaa_

Note both answers above use Raku's trim-trailing routine to get rid of trailing whitespace. Feel free to delete trim-trailing and/or adjust the number of characters chop-ped from the right-hand end of the string.

https://docs.raku.org/routine/chop
https://raku.org

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .