Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I've tried some sed patterns like this from commandlinefu

sed -r "s/('[a-z]+)_([a-z])([a-z]+)/\1\U\2\L\3/"

But somehow it's not working. For one thing they forgot the digits, which I can fix, but this pattern works for one underscore only. So for example if I have a string in file

'foo_bar_foo'

it will convert in to

'fooBar_foo'

. Which is not what I want (I want 'fooBarFoo')

I only want to change strings in file, not the variable names or anything else. So for example this

delta_limits=Limits(general_settings['signal_lower_limit']

Should become this

delta_limits=Limits(general_settings['signalLowerLimit']
share|improve this question
    
What is it you want? 'fooBarFoo' or 'FooBarFoo'? –  Stéphane Chazelas Aug 31 at 13:28
    
@StéphaneChazelas 'fooBarFoo' –  user1685095 Aug 31 at 13:29
    
@StéphaneChazelas Well, no. Not exactly. Because I don't want to change variable names. Only strings in source file. –  user1685095 Aug 31 at 13:33
    
Please add sample input and your desired output for that sample input to your question. –  Cyrus Aug 31 at 13:34
    
@Cyrus I've just did. –  user1685095 Aug 31 at 13:35

2 Answers 2

up vote 6 down vote accepted

If I understand correctly, you want to change _x to X as long as it occurs inside '...' strings.

Then, with GNU sed, you could do:

sed -E ":1;s/^(([^']|'[^']*')*'[^']*)_([^'])/\1\u\3/;t1"

That is replace a _X following '... itself following a sequence of either non-quotes or matched quotes.

Which on an input like:

foo_bar 'ab_cd_ef gh_ij' zz_zz 'aa_bb''
delta_limits=Limits(general_settings['signal_lower_limit']

gives:

foo_bar 'abCdEf ghIj' zz_zz 'aaBb'
delta_limits=Limits(general_settings['signalLowerLimit']

That assumes you don't have strings embedding single quotes (as in 'foo\'bar'). If so, you'd need to account for those \' escapes with:

sed -E ":1;s/^(([^']|'([^\']|\\\\.)*')*'([^\']|\\\\.)*)_([^'])/\1\u\5/;t1"

(also accounts for 'foo\\').

That still doesn't cover "foo'bar" quotes or backslash-continued lines or python's '''it's a multi-line quote'''. You'd need a python parser to be able to cover all the cases.

For your particular case,

sed -E ":1;s/('\w*)_(\w)/\1\u\2/g;t1"

May also be enough (only replaces the _X that follow '\w*). That's the GNU sed equivalent (except for what \w exactly matches) of Glenn's perl approach.

share|improve this answer
    
Seems to work, can you explain how it works also? I know basics of regex, so maybe this wouldn't be that hard to explain. –  user1685095 Aug 31 at 13:39

I'd use perl for this:

perl -pe "1 while s/('\w+)_([^']*)/\$1\\u\$2/" <<END
my_variable = 'a_string_with_snake_case_inside'
delta_llimits=Limits(general_settings['signal_lower_limit']
END
my_variable = 'aStringWithSnakeCaseInside'
delta_limits=Limits(general_settings['signalLowerLimit']

That means: while the search and replace continues to find a match, "1" (a no-op that returns true)

share|improve this answer
    
Thanks for you answer, but I think this should be possible without perl. I could do that in python If I wanted to, or Java, or any language I know. –  user1685095 Aug 31 at 13:41
1  
No problem. perl's just a program (like sed) that happens to be good at text manipulation. –  glenn jackman Aug 31 at 13:44
    
I thought that perl is a programming language... Isn't it? –  user1685095 Aug 31 at 13:53
    
Yes it is. So is sed. –  glenn jackman Aug 31 at 13:57
    
Oh, thank you for enlightening me! I haven't realized that. –  user1685095 Aug 31 at 13:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.