Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to execute specific line of text file in bash. I was wondering is it possible to do that without copying that line in a new file and executing it?

share|improve this question
up vote 3 down vote accepted

Building on @kev's answer (without piping to a new bash): Take his script source

script.sh

echo hello
echo world
echo foo
echo bar

and execute a certain line inside a $(...):

command:

$(sed -n '3p' script.sh)

It will print foo in bash your current shell.

share|improve this answer
    
@ormaaj: I agree with you in discouraging such a concept. On the other hand it comes handy when following instructions from a simple diary (log) file. – fheub Jul 13 '12 at 9:49
    
I agree, this is exactly why am I using it. – Vladimir Perković Jul 13 '12 at 9:55
1  
@fheub: This isn't a good answer because the argument list is built by word-splitting, with pathname expansion enabled. This will fail in all but simple cases. Always quote command substitutions. kev's answer is ok. Mine works in either a child process or the current environment because of the eval (and uses properly escaped input). If you have GNU sed available, a shell command can be executed in pure sed using the e function: sed -n $'3{e\np;q}' file – ormaaj Jul 13 '12 at 10:15
    
@ormaaj: Touché! But Vladimir seems to be looking for a KISS-solution. – fheub Jul 13 '12 at 10:27

script.sh

echo hello
echo world
echo foo
echo bar

command:

sed -n '3p' script.sh | bash

It will print foo

share|improve this answer
    
I think you should pipe to bash as Vladimir wants to execute the line. – Bernhard Jul 13 '12 at 7:27

If you are talking about a shell script, you could do that like in this example:

#!/bin/bash
LINE='less'
#...
LINE="$LINE myfile.txt"
# now we execute that:
$LINE

Another example includes capturing the output for further processing:

#!/bin/bash
LINE="grep foo bar.txt"
OUTPUT=$($LINE)

In the second example, the variable $OUTPUT then contains the results of the executed grep command.

share|improve this answer

Probably not quite what you want, but could be useful to mention:

history -r script.sh

This reads each line of the script into your history list, from which you can execute any line using bash's history expansion feature.


A few failed attempts at reading in just the line you want to execute:

# No command substitution; the argument is added literally
history -s $(sed -n '3p' script.sh)

# Can't seem to read from stdin or from a process substitution
sed -n '3p' script.sh | history -r -
sed -n '3p' script.sh | history -r /dev/stdin
history -r <( sed -n '3p' script.sh )
share|improve this answer

You could but probably shouldn't. Create a library containing functions and source it. This is a very unusual requirement. Bash has actual means of control flow - there's no need to grab strings of code out of files to execute. This can be dangerous.

Here's a "toy" example, not for production use...

#!/usr/bin/env bash

shopt -s extglob

# evalLine filepath line-number
evalLine() {
    [[ -f $1 && $2 == +([[:digit:]]) ]] || return 1
    local x
    # This subtraction compensates for a bug that's since been fixed in 4.2.35 
    mapfile -ts $(($2 - 1)) -n 1 x &&
    ${x:+eval "$x"}
} <"$1"

evalLine /dev/stdin "$1" <<"EOF"
echo "line 1"
f() { echo "$1"; }; f "line 2"
var3='line 3' eval 'echo "$var3"'
EOF

Late edit: Note the comment regarding a bug in mapfile.

share|improve this answer

You must log in to answer this question.

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