0

In reference to this question I still struggle the following single-liner to work

kubectl get ns | while read -r line; do  echo `$line | grep Term | cut -d' ' -f1`; done

I would expect to print out the result of $line | grep Term | cut -d' ' -f1 however it prints out an empty line (echo) and then executes the result of $line | grep Term | cut -d' ' -f1

bash: NAME: command not found

bash: cert-manager: command not found

bash: configmap-4262: command not found

bash: configmap-4430: command not found

Same results with a slightly different approach:

kubectl get ns | while read -r line; do ns=`$line | grep Term | cut -d' ' -f1`; echo $ns; done

What I actually want to achieve is to use the result of $line | grep Term | cut -d' as an input of a shell script e.g.

do ns=`$line | grep Term | cut -d' ' -f1`; ./delete-kube-ns.sh $ns;

or

$line | grep Term | cut -d' ' -f1` | xargs ./delete-kube-ns.sh
papanito
  • 2,349
  • 2
  • 32
  • 60
  • 1
    You're trying to execute the contents of `$line` as a shell command. – Barmar Feb 14 '20 at 16:38
  • To expand on the previous comment, if `$line` is `poo`, then the command `$line | grep` tries to execute `poo` and pipe its output to `grep`. You apparently want `echo "$line" | grep` etc; pay attention to the quotes around the variable, too. Code which doesn't do what you want is often a poor way to explain what you do want. – tripleee Feb 15 '20 at 18:41

4 Answers4

3

Ger rid of the backticks. It's trying to execute the output of kubectl as a shell command. You want to echo $line, not the result of executing it as a command.

kubectl get ns | while read -r line; do  
    echo "$line" | grep Term | cut -d' ' -f1
done

There doesn't really seem to be a need to use while read at all, just pipe kubectl to grep

kubectl get ns | grep Term | cut -d' ' -f1
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Yeah maybe my question was not properly enough, the `echo` was just an example for me on the way to get an understanding. What I want in the end is to something like this ```do ns=`$line | grep Term | cut -d' ' -f1`; ./delete-kube-ns.sh $ns;``` – papanito Feb 15 '20 at 09:33
1

A parameter expansion might be what you want/need, instead of embedding grep and cut inside a while read loop.

#!/usr/bin/env bash

kubectl get ns | while IFS= read -r line; do  
  [[ $line == Term ]] && ns=${line% *}
  echo "$ns"
done

Depending on the pattern match, you might need *Term*

Jetchisel
  • 7,493
  • 2
  • 19
  • 18
1

Any combo of grep and cut (and head, tall, etc, as well as sed) suggests a reimplementation in Awk. Saving one external process is a minor optimization, but this often invites additional simple improvements. For example, should the regex cover the whole line, or is it only really supposed to look for matches in the first field? That's not impossible with grep, either, of course, but quite easy in Awk.

kubectl get ns |
awk '/Term/ { print $1 }'

If you only wanted to look for Term in the first field, that's '$1 ~ /Term/ { ...

You can extend this with a pipe to

... | xargs ./delete-kube-ns.sh

if that's your end goal.

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

With your suggestion I actually could achieve what I intended to do

kubectl get ns | awk '/Term/ { print $1 }' | while IFS= read -r line; do
   ~/bin/kill-kube-ns.sh $line
done
Killed namespace: configmap-4500
Killed namespace: configmap-5062
Killed namespace: configmap-5526
Killed namespace: configmap-5817
Killed namespace: configmap-6143
papanito
  • 2,349
  • 2
  • 32
  • 60