Rancho
Rancho

Reputation: 309

sed delete 1st line and remove leading/trailing white spaces

I am trying to delete the 1st line and removing leading and trailing white spaces in the subsequent lines using sed

If I have something like

line1
     line2
  line3

It should print

line2
line3

So I tried this command on unix shell:

sed '1d;s/^ [ \t]*//;s/[ \t]*$//' file.txt

and it works as expected.

When I try the same in my perl script:

my @templates = `sed '1d;s/^ [ \t]*//;s/[ \t]*$//' $MY_FILE`;

It gives me this message "sed: -e expression #1, char 10: unterminated `s' command" and doesn't print anything. Can someone tell me where I am going wrong

Upvotes: 1

Views: 757

Answers (6)

Jotne
Jotne

Reputation: 41460

This can also be down with awk

awk 'NR>1 {$1=$1;print}' file
line2
line3

Upvotes: 0

tripleee
tripleee

Reputation: 189936

Why would you invoke Sed from Perl anyway? Replacing the sed with the equivalent Perl code is just a few well-planned keystrokes.

my @templates;
if (open (M, '<', $MY_FILE)) {
    @templates = map { s/(?:^\s*|\s*$)//g; $_ } <M>;
    shift @templates;
    close M;
}  else { # die horribly? }

Upvotes: 2

SES
SES

Reputation: 870

As others have mentioned, I would recommend you do this only in Perl, or only in Sed, because there's really no reason to use both for this task. Using Sed in Perl will mean you have to worry about escaping, quoting and capturing the output (unless reading from a pipe) somehow. Obviously, all that complicates things and it also makes the code very ugly.

Here is a Perl one-liner that will handle your reformatting:

perl -le 'my $line = <>; while (<>) { chomp; s/^\s*|\s*$//; print $_; }' file.txt

Basically, you just take the first line and store in a variable that won't be used, then process the rest of the lines. Below is a small script version that you can add to your existing script.

#!/usr/bin/env perl

use strict;
use warnings;

my $usage = "$0 infile";
my $infile = shift or die $usage;

open my $in, '<', $infile or die "Could not open file: $infile";

my $first = <$in>;

while (<$in>) {
    chomp;
    s/^\s*|\s*$//;

    # process your data here, or just print...
    print $_, "\n";
}
close $in;

Upvotes: 1

Joseph R.
Joseph R.

Reputation: 805

You have a typo in your expression. You need a semicolon between the 2 substitution statements. You should use the following instead:

my @templates = `sed '1d;s/^ [ \\t]*//;s/[ \\t]*\$//' $MY_FILE`;

escaping $ and \ as suggested in the other answer. I should note that it also worked for me without escaping \ as it was replaced by a literal tab.

Upvotes: 1

Slaven Rezic
Slaven Rezic

Reputation: 4581

Consider to use safe pipe open instead of backticks, to avoid problems with escaping. For example:

my @templates = do {
    open my $fh, "|-", 'sed', '1d;s/^ [ \t]*//;s/[ \t]*$//', $MY_FILE
        or die $!;
    local $/;
    <$fh>;
};

Upvotes: 1

user507077
user507077

Reputation:

The backticks work like double-quotes. Perl interpolates variables inside them, as you already know due to your use of $MY_FILE. What you may not know is that $/ is actually a variable, the input record separator (by default a newline character). The same is true for the backslashes before the tab character. Here Perl will interpret \t for you and replace it with the tab character. You'll need a second backslash so that sed sees \t instead of an actual tab character. The latter might work as well, though.

Upvotes: 1

Related Questions