we have files with the follwing file name format




we want to capture only the "FILE NAME" and "VERSION" number

so how to remove the first _ , and the last _ in the file name so we can capture the "FILE NAME" and "VERSION" , ( with sed/awk or perl one-liner )


 echo VER_collect_important_info.pl_1.0.2 | <some syntax>

 collect_important_info.pl  1.0.2
  • The XY problem is asking about your attempted solution rather than your actual problem. – Cyrus Jan 18 '18 at 6:55

Perl comes much more naturally to me than the lighter-weight alternatives:

echo VER_collect_important_info.pl_1.0.2 | perl -pe 's/^[^_]*_(.*)_(.*)$/$1 $2/'

If it doesn't matter that this uses a heavier weight process than necessary, I'd stop there.

sed can do it however, it just feels kludgey to have to have to escape basic elements like brackets:

echo VER_collect_important_info.pl_1.0.2 | sed 's/VER_\(.*\)_\(.*\)/\1 \2/'
|improve this answer|||||

This should do the trick

$ echo VER_collect_important_info.pl_1.0.2 | sed 's/_/ /' | sed -r 's/(.*)_/\1 /' | awk -F" " '{print $2"\t"$3}'

The first sed is replacing the first occurrence of _ and second sed does that with the last occurrence of _ and finally awk to print

|improve this answer|||||
$ echo 'VER_collect_important_info.pl_1.0.2' | 
    perl -F_ -lane 'print join("_", @F[1..@F-2]), " ", @F[@F-1]'
collect_important_info.pl 1.0.2

Note: perl arrays start from 0, not 1 so the array index for the second field is [1], not [2].

This splits the input into an array (@F), separated by _ underscore characters. Then it prints the 2nd through to the 2nd-last field (@F[1..@F-2]) joined by underscores, followed by a space, and then the last field (@F[@F-1]).

|improve this answer|||||

find + bash solution:

Sample files:

$ ls -1 VER_*_[0-9]*[0-9]

find . -type f -name "VER_*_[0-9]*[0-9]" -exec \
        bash -c 'v=${1##*_}; f=${1#*_}; f=${f%_*}; echo $f $v' _ {} \;

The output:

collect_some_info.pl 3.4.2
collect_important_info.pl 1.0.2
|improve this answer|||||

With awk you can use:

echo VER_collect_important_info.pl_1.0.2 | awk -F '_' '{for (i=2; i<NF; i++) {{printf $i} if (i!=NF-1) printf "_"} printf " " $NF "\n"}'
|improve this answer|||||

I got mentioned result by using combination of sed and awk

echo VER_collect_important_info.pl_1.0.2 |sed -r "s/_/ /1"| sed "s/_/ /3"| awk '{print $2,$NF}'
|improve this answer|||||

Just run this perl script and pass the directory to look into as it's argument:


use strict;
use warnings;

my $dir = $ARGV[0];
my @files = `find $dir -type f -name "VER_*_[0-9]*[0-9]"`;

my $all_files;
foreach my $file (@files) {
    $file =~ /VER_(.*)_(.*)/;
    $all_files .= $1."  ".$2."\n";

print $all_files if ($all_files);

I ran this script by passing current directory (.) as argument to it (which contains VER_collect_important_info.pl_1.0.3).

[mask@cent ~]$ perl separate_file_version.pl .  
collect_important_info.pl  1.0.3
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.