0

we have files with the follwing file name format

VER_{FILE NAME}_{VERSION}

example

  VER_collect_important_info.pl_1.0.2

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 )

example

 echo VER_collect_important_info.pl_1.0.2 | <some syntax>

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

7 Answers 7

2

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/'
0

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

0
$ 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]).

0

find + bash solution:

Sample files:

$ ls -1 VER_*_[0-9]*[0-9]
VER_collect_important_info.pl_1.0.2
VER_collect_some_info.pl_3.4.2

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
0

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"}'
0

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}'
0

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

#!/usr/bin/perl

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);

Example:
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

You must log in to answer this question.

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