Append to sed output [duplicate] - unix

I'm trying to add && \ on end of each line on a text file except the last line.
Sample input:
ps
mkdir repo
cd repo/
touch file1.txt
Expected output:
ps && \
mkdir repo && \
cd repo/ && \
touch file1.txt
First attempt
I tried this, but it outputs && \ on each line including the final line:
awk '{print $0"&& \\"}' RS="\r*\n\r*"
Second attempt
I tried using sed:
sed '1s/^//;$!s/$/"&&" \\/;$s/$//'
This seems to add extra newlines:
ps
&& \
mkdir repo
&& \
cd repo/
&& \
touch file1.txt

You could use sed for something that simple:
printf "line 1\nLine 2\nLine 3\n" | sed '$ ! s/$/ \&\& \\ /'
Output
line 1 && \
Line 2 && \
Line 3

Related

error while running a R script in a bash script

e made a bash script as follows:
#! /bin/bash
OUTDIR=".//DATA/share/pipelines/results/"
INDIR="./DATA/share/pipelines/test_data/infile/"
projectname=$1
input_bam=$2
bins=$3
mkdir OUTDIR || true
of="${OUTDIR}"
ind="${INDIR}"
./DATA/share/pipelines/script.R \
-b "${bins}" \
-c "${projectname}" \
-o "${of}" \
-i "${ind}"
echo "first step is done"
when I run the script using the following command:
bash first.sh 30 beh
I will get this error:
mkdir: cannot create directory ‘OUTDIR’: File exists
first.sh: line 17: ./DATA/share/pipelines/script.R: No such file or directory
first step is done
do you know how to solve the problem?
When you call
bash first.sh 30 beh
$1 holds 30, $2 holds beh and $3 is not defined.
input_bam ist set to $2 but is never used.
With [ ! -d ${OUTDIR} ] you should be able to test if the directory exists.
#! /bin/bash
#Please check if it should be
# relative to the current working directory (starting with './')
# or absolute (starting with '/')
BASEDIR="/DATA/share/pipelines/" #"./DATA/share/pipelines/"
OUTDIR=${BASEDIR}"results/"
INDIR=${BASEDIR}"test_data/infile/"
projectname=$1
input_bam=$2 #This is never used
bins=$3 #This is not defined when callin >bash first.sh 30 beh<
[ ! -d ${OUTDIR} ] && mkdir ${OUTDIR} #Think you would create ${OUTDIR}
of="${OUTDIR}"
ind="${INDIR}"
./DATA/share/pipelines/script.R \
-b "${bins}" \
-c "${projectname}" \
-o "${of}" \
-i "${ind}"
echo "first step is done"

For loop variable is empty in gmake

I have a list of header files created thus:
expand=$(1)/$(1).h
HDRS=$(foreach x, $(DIRS), $(call expand,$(x)))
Which yields a list like a/a.h b/b.h ...
but when I use this in a for loop:
for i in $(HDRS) ; do \
echo $$i \
cp $$i $(some_dir) \
done
$$i is empty. And the cp fails, having only one argument.
The usual variants of $$i ( $i, $$i, $(i), ${i} ), don't change anything, nor do the usual variants of $(HDRS) ("$(HDRS)", etc.).
gmake echos the for-loop as
for i in a.h b.h ; \
do \
echo $i \
cp $i somedir \
done
Which looks correct.
But the implicit bash shell emits an error "/bin/sh -c: line 5: syntax error: unexpected end of file"
gmake then exits due to the failed command.
Due to the \, make emits the recipe as a single line. This confuses the shell. Try this instead, using ; in place of the line terminator:
for i in a.h b.h ; \
do \
echo $i ; \
cp $i somedir ; \
done

How to use variable to search and replace using sed or awk?

I am trying to find and replace a value using variable with the help of sed and awk but not getting any output -
#cat temp.txt
this is Testing of date : 2016-11-25 07:20:10
It is printing the variable but not working in gsub function -
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{print srch,repl}' temp.txt
2016-11-25 07:20:10 [25/Nov/16:07:20:10]
I tried below awk command -
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{gsub("srch","repl",$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub(srch,repl,$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub("$srch","$repl",$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub(srch,repl,$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{print gsub(srch,repl,$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub("srch","repl",$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub("$srch","$repl",$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub("$srch","$repl",$0)}' temp.txt
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub(srch,repl,$0)}' temp.txt
#var1="2016-11-25 07:20:10"
#var2="[25/Nov/16:07:20:10]"
#echo $var1 $var4
2011-11-25 07:20:10 [25/Nov/11:07:20:10]
#awk -v srch="$var1" -v repl="$var4" '{ gsub(srch,repl,$0)}' temp.txt
With sed command -
#echo $var1 $var4
2011-11-25 07:20:10 [25/Nov/11:07:20:10]
sed 's/"$var1"/"$var4"/' temp.txt
sed 's/$var1/'"${var4}"'/' temp.txt
sed 's|$var1|'"${var4}"'|' temp.txt
sed 's/\$var1/${var4}/' temp.txt
sed 's/\$var1/$var4/' temp.txt
sed "s/"$var1"/"$var4"/" temp.txt
sed 's/'$var1'/'$var4'/' temp.txt
sed 's/'$var1'/'$var4\/' temp.txt
sed -e "s/${var1}/${var4}/' temp.txt
sed -e "s/${var1}/${var4}/" temp.txt
sed "s/$var1/$var4/" temp.txt
sed 's/'"$var1"'/'"$var4"'/' temp.txt
sed 's/'"$var1"'/'$var4'/' temp.txt
Not sure what i am missing.
Expected output -
#this is Testing of date : [25/Nov/11:07:20:10]
this one works, but you need to add print or nothing will be printed:
awk -v srch="2016-11-25 07:20:10" -v repl="[25/Nov/16:07:20:10]" '{ gsub(srch,repl,$0); print}' temp.txt
result:
this is Testing of date : [25/Nov/16:07:20:10]
with sed you can do it as well (as long as you use double quotes, or variables won't be evaluated), but since replacement string contains slashes, you have to change sed expression delimiter or you get a sed parsing error, I chose #
$ var1="2016-11-25 07:20:10"; var4="[25/Nov/11:07:20:10]"
$ sed "s#$var1#$var4#" temp.txt
result:
this is Testing of date : [25/Nov/11:07:20:10]
It would be:
var1="2016-11-25 07:20:10"
var2="[25/Nov/16:07:20:10]"
awk -v srch="$var1" -v repl="$var2" '{gsub(srch,repl)} 1' temp.txt
sed 's#'"$var1"'#'"$var2"'#g' temp.txt
You should also read Is it possible to escape regex metacharacters reliably with sed as the above would fail if var1 contained RE metacharacters or var2 contained backreferences.
At a bit of a tangent - I would tackle it in perl and parse your date. (I know you didn't ask about perl, but I think it's a good fit for this - it's installed in most of the places you have sed or awk available)
It would work a bit like this:
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
#iterate __DATA__ special filehandle
while ( <DATA> ) {
#extract time via regex
my ( $time_str ) = m/([\d\-]+\s+[\d\:]+)$/;
next unless $time_str;
#parse it into a Time::Piece object
my $timestamp = Time::Piece -> strptime ("$time_str", "%Y-%m-%d %H:%M:%S");
#print it using a new format string
my $new_time_str = $timestamp -> strftime("%d/%b/%y:%H:%M:%S");
#replace old with new in line
s/$time_str/\[$new_time_str\]/;
#print current line
print;
}
__DATA__
this is Testing of date : 2016-11-25 07:20:10
And for the sake of a command line solution, that condenses into:
perl -pe '($ts)=m/([\d\-]+\s+[\d\:]+)$/;s{$ts}{Time::Piece->strptime($ts,"%Y-%m-%d %H:%M:%S")->strftime("[%d/%b/%y:%H:%M:%S]")}e;'
You can pipe into this, or specify a filename as an argument, just like you would with sed or awk.

Match specific lines in sed command

How can I match a set of specific lines for a substitution command?
(incorrect):
sed -e'71,116,211s/[ ]+$//' ...
I want to strip trailing whitespace on lines 71, 116 and 211 only
You could try something like:
awk 'NR== 71 || NR == 116 || NR == 211 {sub(/ *$/,"",$0)}{print $0}'
or
sed '71s/ *$//;116s///;211s///'
sed '71bl;116bl;211bl;b;:l;s/[ ][ ]*$//' input
For any specified line, this script jumps to the label l. Other lines will jump to the end of the script with the bare branch.
And an awk solution:
awk -v k="71,116,221" 'BEGIN{split(k,a,",")}
(NR in a) { sub(/ *$/,"",$0) }1' input
This might work for you (GNU sed):
sed -r '/\s+$/!b;71s///;116s///;221s///' file
or perhaps:
sed -e '/ *$/!b' -e '71s///' -e '116s///' -e '221s///' file
or as has been said already:
sed -e '71ba' -e '116ba' -e '221ba' -e 'b' -e ':a' -e 's/ *$//' file

Unix script to delete file if it contains single line

Consider I have a file abcde.txt which may contain one or more lines of text. I want a script that will DELETE the file if it contains single line.
Something like, if 'wc -l abscde.txt' = 1 then rm abscde.txt
My system : Solaris
Here's a simple bash script:
#!/bin/bash
LINECOUNT=`wc -l abscde.txt | cut -f1 -d' '`
if [[ $LINECOUNT == 1 ]]; then
rm -f abscde.txt
fi
delifsingleline () {
if [ $(cat $1 | wc -l) = "1" ]
then
echo "Deleting $1"
echo "rm $1"
fi
}
Lightly tested on zsh. Should work on bash as well.
This is (mostly) just a reformat of Ben's answer:
wc -l $PATH | grep '^1 ' > /dev/null && rm -f $PATH

Resources