Command Line Magic Part 2: Variables and Loops in Bash



[ad_1]

You only need to master iterative creation of commands interactively to become a command line assistant.
Enlarge / You only need to master iterative creation of commands interactively to become a command line assistant.

In our first tutorial on command line magic, we covered simple redirection and the basics of sed, awk, and grep. Today we’re going to introduce the concepts of simple variable substitution and looping, again, focusing specifically on the Bash command line itself, rather than Bash. scenarisation.

If you need to write a script for repeated use, especially a script with significant logical branching and evaluation, I highly recommend “real language” instead of Bash. Fortunately, there are a lot of options. I am personally a huge fan of Perl, in part because it is available on virtually any * nix system you will come across. Others might reasonably choose, say, Python or Go instead, and I wouldn’t judge.

The real point is that we are focusing on the command line itself. All of the following is something you can easily learn to think about and use in real time with a little practice.

Set and get values ​​in Bash

Bash handles variables a bit oddly compared to one of the “real” languages ​​I have used. In particular, you should refer to the same variable with different syntax when setting its value relative to retrieval.

Let’s see a very simple example:

me@banshee:~$ hello="Hello, world!"

me@banshee:~$ echo $hello
Hello, world!

If you’ve never worked with variables in Bash before, you might think there’s a typo in the example above. We fix the value of hello but reread its value as $hello. It’s not a mistake, you don’t use the first one $ when defining / tuning a variable, but you must use it when reading the same variable later.

Destroy variables

If we need to clear this variable, we can use the unset command – but, again, we have to refer to hello in the place of $hello:

me@banshee:~$ echo $hello
Hello, world!

me@banshee:~$ unset $hello
bash: unset: `Hello,': not a valid identifier
bash: unset: `world!': not a valid identifier

me@banshee:~$ unset hello

me@banshee:~$ echo $hello


Thinking of the error messages we get when we try to unset $hello should clarify the problem. when we unset $hello, we pass the value of hello To unset rather than passing the name of the variable itself. It means exactly what you think it does:

me@banshee:~$ hello="Hello, world!"

me@banshee:~$ myhello="hello"

me@banshee:~$ unset $myhello

me@banshee:~$ echo $hello


Although the back and forth between SEO hello and $hello is deeply disturbing if you are only familiar with “real” languages, Bash is at least relatively consistent in the use of each style. With a little practice, you will get used to it, even if you never really feel comfortable about that.

Variable range

Before we go through the basics of variables, we need to talk about the scope of variables. Basically, a Bash variable has a scope limited to only the running process. It will not pass your variables to any child process you initiate. We can see it in action more easily by calling bash of bash:

me@banshee:~$ hello="Hello, world!"

me@banshee:~$ echo $hello
Hello, world!

me@banshee:~$ bash

me@banshee:~$ echo $hello

me@banshee:~$ exit
exit

me@banshee:~$ echo $hello
Hello, world!

In our original Bash session, we set the variable hello to equal “Hello, world!” and access it successfully with the echo order. But when we start a new one bash session, hello is not passed to this child session. So when we try again to echo $hello, we get nothing. But after exiting the child shell, we can succeed again echo $hello and receive the value we initially set.

If you need to carry variables defined in a session into a child process, you should use the export order:

me@banshee:~$ unset hello

me@banshee:~$ hello="Hello, future children!"

me@banshee:~$ export hello

me@banshee:~$ bash

me@banshee:~$ echo $hello
Hello, future children!

As you can see, export successfully marked our variable hello to pass to child processes – in this case, another instance of bash. But the same technique works, the same way, for calling all child process that references environment variables. We can see it in action by writing a very small Perl script:

me@banshee:~$ cat perlexample
    #!/usr/bin/perl
    print "$ENV{hello}n";
    exit 0;

me@banshee:~$ hello="Hello from Perl!"

me@banshee:~$ ./perlexample

me@banshee:~$ export hello

me@banshee:~$ ./perlexample
Hello from Perl!

Just like our previous example of a child session of bash, our Perl script cannot read our hello environment variable unless we have first export this.

The last thing we’ll say about export is that it can be used to set the value of the variable it exports, in one step:

me@banshee:~$ export hello="Hi again!"

me@banshee:~$ ./perlexample
Hi again!

Now that we understand how to set and read variable values ​​on the command line, let’s move on to a very useful operator: backticks.

Capture command output with backticks

me@banshee:~$ echo test
test

me@banshee:~$ echo `echo test`
test

The backticks The operator captures the output of a command. Sounds pretty straightforward, right? In the example above, we demonstrate that the output of the command echo test is, of course, “test” – so when we echo `echo test` we get the same result.

We can go further and instead assign the output of a command to a variable:

me@banshee:~$ du -hs ~
13G	/home/me

me@banshee:~$ myhomedirsize=`du -hs ~`

me@banshee:~$ echo $myhomedirsize
13G /home/me

Finally, we can combine this with the lessons from our first tutorial and remove the first column from duthe output to assign to our variable:

me@banshee:~$ myhomedirsize=`du -hs ~ | awk '{print $1}'`

me@banshee:~$ echo $myhomedirsize
13G

At this point, we understand how variables and the backticks operator work. So let’s talk about simple loopback structures.

For loops in Bash

me@banshee:~$ y="1 2 3"

me@banshee:~$ for x in $y ; do echo "x equals $x" ; done
x equals 1
x equals 2
x equals 3

The above example shows concisely how a simple for the loop works in Bash. It cycles through a supplied sequence of items, assigning the current item in the list to a loop variable. We used semicolons to separate the for loop itself, the do command that marks the inside of the loop, and the done which lets us know that the loop is over. Alternatively, we could also enter them as technically separate lines.

me@banshee:~$ y="1 2 3"

me@banshee:~$ for x in $y
> do
> echo "x=$x"
> done
x=1
x=2
x=3

In this example, the leading chevrons aren’t something you type, they’re a prompt provided by Bash itself. This lets you know that you are still in a loop despite hitting Enter. And this is important, because you can have as many commands as you want in the loop itself!

me@banshee:~$ y="1 2 3"

me@banshee:~$ for x in $y ; do echo "x equals $x" ; echo "x=$x" ; echo "next!" ; done
x equals 1
x=1
next!
x equals 2
x=2
next!
x equals 3
x=3
next!

As you can see, we can chain as many orders as we want together in our for loop. In the loop, each command can refer to the loop variable if it wants, or it can ignore the loop variable completely.

So far we have only looked at the numbers in the sequences, but the for the loop doesn’t care a bit. All the sequence of elements, in any order, will work:

me@banshee:~$ y="cats dogs bears"

me@banshee:~$ for x in $y ; do echo "I like $x" ; done
I like cats
I like dogs
I like bears

Finally, you don’t have to supply a variable to the list; you can also integrate it directly into the loop:

me@banshee:~$ for x in "cats dogs bears" ; do echo "I like $x" ; done
I like cats
I like dogs
I like bears

[ad_2]

Source link