Is there a way for me to simplify these echos? [du

2020-05-09 18:24发布

I am still learning how to shell script and I have been given a challenge to make it easier for me to echo "Name1" "Name2"..."Name15" and I'm not too sure where to start, I've had ideas but I don't want to look silly if I mess it up. Any help?

I haven't actually tried anything just yet it's all just been mostly thought.

#This is what I wrote to start 

#!/bin/bash

echo "Name1"
echo "Name2"
echo "Name3"
echo "Name4"
echo "Name5"
echo "Name6"
echo "Name7"
echo "Name8"
echo "Name9"
echo "Name10"
echo "Name11"
echo "Name12"
echo "Name13"
echo "Name14"
echo "Name15"

My expected results are obviously just for it to output "Name1" "Name2" etc. But I'm looking for a more creative way to do it. If possible throw in a few ways to do it so I can learn. Thank you.

标签: bash shell
3条回答
够拽才男人
2楼-- · 2020-05-09 18:37

A few esoteric solutions, from the least to the most unreasonable :

  • base64 encoded string :

    base64 -d <<<TmFtZTEKTmFtZTIKTmFtZTMKTmFtZTQKTmFtZTUKTmFtZTYKTmFtZTcKTmFtZTgKTmFtZTkKTmFtZTEwCk5hbWUxMQpOYW1lMTIKTmFtZTEzCk5hbWUxNApOYW1lMTUK
    

The weird chain is your expected result encoded in base64, an encoding generally used to represent binary data as text. base64 -d <<< weirdChain is passing the weird chain as input to the base64 tool and asking it to decode it, which displays your expected result

  • generate an infinite stream of "Name", truncate it, use line numbers :

    yes Name | awk 'NR == 16 { exit } { printf("%s%s\n", $0, NR) }'
    

yes outputs an infinite stream of what it's passed as argument (or y by default, used to automatize interactive scripts asking for [y/n] confirmation). The awk command exits once it reaches the 16th line, and otherwise prints its input (provided by yes) followed by the line number. The truncature could as easily be done with head -15, and I've tried using the nl "number line" utility or grep -n to number lines, but they always added the line numbers as prefix which required an extra re-formatting step.

  • read random binary data and hope to stumble on all the lines you want to output :

    timeout 1d strings /dev/urandom | grep -Eo "Name(1[0-5]|[1-9])" | sort -uV
    

    strings /dev/urandom will extract ascii sequences from the binary random source /dev/urandom, grep will filter those which respect the format of a line of your expected output and sort will reorder those lines in the correct order. Since sort needs to have a received its whole input before it reorders it and /dev/urandom won't stop producing data, we use timeout 1d to stop reading from /dev/urandom after a whole day in hope it has sifted through enough random data to find your 15 lines (I'm not sure that's even remotely likely).

  • use an HTTP client to retrieve this page, extract the bash script you posted and execute it.

    my_old_script=$(curl "https://stackoverflow.com/questions/57818680/" | grep "#This is what I wrote to start" -A 18 | tail -n+4)
    eval "$my_old_script"
    

    curl is a command line tool that can be used as an HTTP client, grep with its -A 18 parameter will select the "This is what I wrote to start" text and the 18 lines that follow, tail will remove the first 3 lines, and eval will execute your script.
    While it will be much more efficient than the previous solution, it's an even less reasonable solution because high-rep users can edit your question to make this solution execute arbitrary code on your computer. Ideally you'd be using an HTML-aware parser rather than basic string manipulation to extract the code, but we're not talking about best practices here...

查看更多
Deceive 欺骗
3楼-- · 2020-05-09 18:40

The easiest (possibly not the most creative) way to do this is to use printf:

printf "%s\n" name{1..15}

This relies on bash brace expansion {1..15} to have the 15 strings.

查看更多
女痞
4楼-- · 2020-05-09 18:55

Use a for loop

for i in {1..15};do echo "Name$i";done
查看更多
登录 后发表回答