LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-23-2022, 06:03 AM   #1
vanKey
LQ Newbie
 
Registered: Jun 2022
Posts: 17

Rep: Reputation: 0
for-loop in bash


Hello all,

I have to write a for-loop, that will go through every line and replace, if present, the second minus sign by e-.

content of the test.dat-file:
Code:
0.500000
-0.50000
-1.000-1
-0.50000
content of the corrected file:
Code:
0.500000
-0.50000
-1.000e-1
-0.50000

I tried
Code:
awk 'BEGIN{FS=OFS=";"} {gsub(/\-/, "e-", $1)} 1' test.dat
,
but this will replace all minus signs. I only want to convert the second minus sign of each line.


Has anyone an idea, how to to that?


Kind regards
vanKey

Last edited by vanKey; 06-23-2022 at 06:19 AM.
 
Old 06-23-2022, 06:31 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,298
Blog Entries: 1

Rep: Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619Reputation: 1619
Code:
echo '012-345-678-9' |
sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1-\2e-\3/'
result:
Code:
012-345e-678-9

Last edited by NevemTeve; 06-23-2022 at 06:33 AM.
 
1 members found this post helpful.
Old 06-23-2022, 06:31 AM   #3
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 18,638

Rep: Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323
yes, just it is not bash (but awk).
Anyway, you need to use a different regexp (for example):
Code:
gsub(/0[-]/, "0e-", $1)
(not tested)
 
1 members found this post helpful.
Old 06-23-2022, 06:49 AM   #4
vanKey
LQ Newbie
 
Registered: Jun 2022
Posts: 17

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by pan64 View Post
yes, just it is not bash (but awk).
Anyway, you need to use a different regexp (for example):
Code:
gsub(/0[-]/, "0e-", $1)
(not tested)
The problem is, that it won't work for

Code:
0.500000
-0.50000
-1.001-1
-1.002-1
-0.50000
Kind regards
vanKey

Last edited by vanKey; 06-23-2022 at 07:13 AM.
 
Old 06-23-2022, 07:10 AM   #5
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 18,638

Rep: Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323Reputation: 6323
probably you made a mistake. It works for me. From the other hand you can modify that regexp to fit your needs.
 
1 members found this post helpful.
Old 06-23-2022, 07:20 AM   #6
vanKey
LQ Newbie
 
Registered: Jun 2022
Posts: 17

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by pan64 View Post
probably you made a mistake. It works for me. From the other hand you can modify that regexp to fit your needs.
yeah, i changed my post to the following:

It does not work for

Code:
0.500000
-0.50000
-1.001-1
-1.002-1
-0.50000
Kind regards
vanKey
 
Old 06-23-2022, 07:47 AM   #7
vanKey
LQ Newbie
 
Registered: Jun 2022
Posts: 17

Original Poster
Rep: Reputation: 0
Code:
gsub(/1[-]|2[-]/, "1e-", $1)
could do, but it still only replaces everything with "1e-" then.
 
Old 06-23-2022, 02:53 PM   #8
teckk
Senior Member
 
Registered: Oct 2004
Distribution: Arch
Posts: 4,155
Blog Entries: 4

Rep: Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439Reputation: 1439
Basic Examples, not the whole answer. You finish it.
Code:
a=(
0.500000
-0.50000
-1.001-1
-1.002-1
-0.50000
)

for i in "${a[@]}"; do
    echo "Last 2 are : "${i: -2}""
done

for i in "${a[@]}"; do
    if [[ "${i: -2}" =~ ^- ]]; then
        echo "These end in -? : "$i""
    fi
done

for i in "${a[@]}"; do
    if [[ "${i: -2}" =~ ^- ]]; then
        echo "${i%??}"
    else
        echo "$i"
    fi
done

for i in "${a[@]}"; do
    if [[ "${i: -2}" =~ ^- ]]; then
        echo "${i%??}e-"
    else
        echo "$i"
    fi
done
 
1 members found this post helpful.
Old 06-23-2022, 06:53 PM   #9
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=14, FreeBSD_12{.0|.1}
Posts: 5,892
Blog Entries: 23

Rep: Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887Reputation: 3887
Quote:
Originally Posted by vanKey View Post
Code:
gsub(/1[-]|2[-]/, "1e-", $1)
could do, but it still only replaces everything with "1e-" then.
Rather than telling others that their suggestions do not work for some case, try to understand why they do not work and from that point ask yourself how they might be modified to work for the case at hand and try to make the change! You will learn much more and more quickly that way!

When attempting to write more complex regular expressions, I find it very useful to write out a description of what I want in concise, plain language, then using that as a sort of specification try to implement the behavior in a regular expression.

Again, please review the Site FAQ for guidance in asking well formed questions. Especially visit the link from that page, How to Ask Questions the Smart Way for discussion of things to consider when asking others for help.
 
Old 06-23-2022, 11:13 PM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,899

Rep: Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123Reputation: 3123
As others have said, your solution is in awk and not bash and there is no for loop, so the starting point would be to right your question with the correct information.

As you are using awk, I would bookmark http://www.gnu.org/software/gawk/man...ode/index.html

Now based on your first attempt and example:
Code:
awk 'BEGIN{FS=OFS=";"} {gsub(/\-/, "e-", $1)} 1' test.dat
Code:
0.500000
-0.50000
-1.000-1
-0.50000
My first question would be, why are you setting FS and OFS to something that does not appear in your input?

Based on your requirement:
[quote]go through every line and replace, if present, the second minus sign by e-.[/code]
I assume this means we only want to worry about lines with 2 minus signs, so the following would be ignored:
Code:
1.000-1
The above being the case, your main function call should have something telling it to firstly, only act on lines with 2 minus signs:
Code:
awk 'split($0,a,"-") == 3{<do change here>}' file
Then the other nice thing you could look at in the manual is the gensub command:
Code:
gensub(regexp, replacement, how [, target])
Focus on the "how":
Quote:
If how is a string beginning with ‘g’ or ‘G’ (short for “global”), then replace all matches of regexp with replacement. Otherwise, treat how as a number indicating which match of regexp to replace.
 
Old 06-24-2022, 12:12 AM   #11
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,018

Rep: Reputation: 895Reputation: 895Reputation: 895Reputation: 895Reputation: 895Reputation: 895Reputation: 895
sed has the /N modifier (Nth match)
Code:
sed 's/-/e-/2'

Last edited by MadeInGermany; 06-24-2022 at 08:49 AM.
 
1 members found this post helpful.
Old 06-26-2022, 03:15 AM   #12
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,018

Rep: Reputation: 895Reputation: 895Reputation: 895Reputation: 895Reputation: 895Reputation: 895Reputation: 895
A sed solution that replaces the first dash not at the beginning:
Code:
sed 's/\(.\)-/\1e-/'
The dot is a wildcard; because it is substituted it needs to be captured with \( \) and restored with \1

You can precise the wildcard to match only a digit, then an existing e would not match (and insert another e).
Code:
sed 's/\([0-9]\)-/\1e-/'

Last edited by MadeInGermany; 06-26-2022 at 11:53 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 03:49 PM
Bash script issue (for loop inside a loop) Mperonen Programming 3 08-08-2013 02:14 AM
[SOLVED] Bash - While Loop reading from two lists simultaneously - nested while loop wolverene13 Programming 11 10-01-2011 05:00 PM
[SOLVED] [BASH] non-empty variable before loop end, is empty after exiting loop aitor Programming 2 08-26-2010 09:57 AM
bash loop within a loop for mysql ops br8kwall Programming 10 04-30-2008 03:50 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:54 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration