3

I want to find the number of new lines in a string and then use this number in a while loop as the limit.

I can find and write the number of lines using:

echo "$MY_STRING" | grep -c '$'

In order to have the number of lines as integer and use it in while loop I do this:

MYNUM="$MY_PEERS" | grep -c '$'

However, this line writes 0, which is not the number of lines in my string, immediately to the terminal. Moreover, I cannot use MYNUM in a while loop. (I use $MYNUM in the while) How can I obtain number of lines so that I can use it in a while loop as the limit?

Eric
  • 41
  • 3
  • I think your use of echo is the issue here, use echo -e to allow interpretation of \n in the string.. or use printf as echo adds a \n on its own, or perhaps echo -ne will work... also, wc -l would be an alternate to grep -c '$' – Sundeep Mar 12 '17 at 05:04
  • Note the number of lines (grep -c (all)) is not the number of newline characters (wc -l) if the last line is unterminated, although most 'good' data doesn't use an unterminated last line. – dave_thompson_085 Mar 12 '17 at 16:52

3 Answers3

3

While I don't fully understand why you need this, this is one way that you can get it done. The key is the $( ) to capture the output and assign it to a variable.

Code:

#!/usr/bin/env bash
IFS='' read -r -d '' TEST_STR <<-'EOF'
    Test text
    quick brown fox
    lazy dog
EOF

NEW_LINE_COUNT=$(echo "$TEST_STR" | wc -l)

echo "$TEST_STR"
echo "$NEW_LINE_COUNT"

Results:

Test text
quick brown fox
lazy dog

4
  • Great! Thank you! It works as I want it. For my project I create number of P2P stations. When a station discovers other stations the results return as a string each line having one device. Then, I need to check the properties of each single discovered device. I plan doing this in a while loop. This is why I needed this information. I am a new guy for Linux shell, so I don't even know very basic operations. Thank you! – Eric Mar 12 '17 at 05:25
2

You don't need to count lines in your multiline string to look at the individual devices. The for loop in tandem with array variables can be put to use here like as:

IFS=$'\n' read -d '' -r -a Multi_Line_Str <<STR
    $(printf '%s\n' 'device_'{A..E})
STR

for device in "${Multi_Line_Str[@]}"
do
    echo "<$device>"
done
2

If you have a multi-line string, you may simply use wc -l to count the number of lines in it:

printf '%s' "$string" | wc -l

To store that number in a variable:

nlines=$( printf '%s' "$string" | wc -l )

However, you don't need this number for doing a while loop:

printf '%s' "$string" |
while read -r line; do
   # do something with "$line"
done

Depending on what you're doing with each line, you may not need a while loop at all:

printf '%s' "$string" | awk '<some awk script>'

Depending on how the data is generated, you may not even have to store it in a multi-line variable at all:

some_command | some_line_by_line_processing

Here, some_command may be a while loop, a collection of commands in a subshell ((...)) or a simple command that generates output and some_line_by_line_processing may likewise be a simple command (like awk) or a loop or whatever other thing you need to process the output of the first part of the pipeline line by line.

Kusalananda
  • 333,661
  • Thank you for your command! 3rd part of your answer seems to be what I want to do. Here's the specific direction for what I want to do. I have a string that consists of MAC addresses of devices, say echo "$MY_PEERS" yields00:00:00:00:00:01 00:00:00:00:00:02` – Eric Mar 12 '17 at 19:50