YAML extension, Search 2 Value and Replace



  • Hi,
    Here is an example of what I want to change:

    Id: 840002
        AegisName: Adulter_F_Launcher
        Name: Adulter Fides Launcher
        Type: Weapon
        SubType: Grenade
        Weight: 3000
        Attack: 350
        Range: 9
        Slots: 2
        Jobs:
          Rebellion: true
        Locations:
          Both_Hand: true
        WeaponLevel: 4
        EquipLevelMin: 180
        Script: |
          .@r = getrefine();
          bonus2 bSkillAtk,"RL_D_TAIL",10;
          bonus bBaseAtk,18*(.@r/3);
          if (.@r>=7) {
             bonus2 bSkillAtk,"RL_D_TAIL",20;
             if (.@r>=9) {
                bonus2 bSkillCooldown,"RL_D_TAIL",-2000;
                if (.@r>=11) {
                   bonus2 bSkillAtk,"RL_D_TAIL",25;
                   if (.@r>=12) {
                      bonus bLongAtkRate,15;
                   }
    

    I want to search for these two value in every Id table:
    Type: Weapon
    Slots: 2

    And change the slots to:
    Slots: 4
    These slots can have a value between 0-4

    Thank you in advance…



  • @Mark-Lozada

    Try the following S/R regex, a simple variation of @guy038’s reply to a former question from you:

    Search: (?s-i)(Type: Weapon.*?\s+Slots:) [0-4]
    Replace: \1 4
    

    Hope this helps. Also try to read the regex guide in the FAQ section of this forum. Thank you



  • @Mark-Lozada ,

    The file format is mildly different than the one from your last question, but the concept of the answer will still be the same. However, since re-reading that thread, I see that they never explained how it worked, or even linked you to our regex FAQ, so you’ll get a second freebie out of this one.

    While typing this up, I saw that @astrosofista beat me to an answer. However, I made a more-restrictive answer, assuming that the Weapon and Slots had to be within the same Id: block in your YAML. However, his looks a lot more like what @guy038 presented in the last question. So I will present it here.

    • FIND = (?sx) ^Id: ((?!^Id:).)* (Type:\h*Weapon) ((?!^Id:).)* Slots:\h*\K[0-4]
    • REPLACE = 4
    • MODE = Regular Expression
    • hit REPLACE ALL

    Mine will take shortened example data like the following:

    Id: 840002
        AegisName: Something
        Type: Weapon
        OtherParameters: here
        Slots: 2
    Id: 840003
        AegisName: Different
        Type: Flower
        OtherParameters: here
        Slots: 2
    Id: 840004
        AegisName: Something
        Type: Weapon
        OtherParameters: here
        Slots: 0
    

    and convert it to

    Id: 840002
        AegisName: Something
        Type: Weapon
        OtherParameters: here
        Slots: 4
    Id: 840003
        AegisName: Different
        Type: Flower
        OtherParameters: here
        Slots: 2
    Id: 840004
        AegisName: Something
        Type: Weapon
        OtherParameters: here
        Slots: 4
    

    … notice that the Flower doesn’t change its slots, but the two weapons do.

    A brief explanation of each piece:

    • (?sx) = this turns on . matches newline and makes it so that spaces in the regex are for readability (and to match a literal space character, you have to use one of the escape characters, like \x20 for just the space, or \h for space-or-tab)
    • ^Id: = matches Id: as long as it is at the start of the line
    • ((?!^Id:).)* = fancy: this matches any character, as long as the character isn’t the start of ^Id: (ie, as long as it doesn’t go into the next Id block)
    • (Type:\h*Weapon) = this matches Type: followed by 0 or more spaces or tabs, followed by Weapon
    • ((?!^Id:).)* = same as before
    • Slots:\h* = matches Slots: followed by 0 or more spaces or tabs
    • \K = this resets the match, so we don’t need to have stored all the previous stuff, even though all that went before must match.
      Unfortunately, this has the side effect of requiring REPLACE ALL instead of doing single REPLACE multiple times.
    • [0-4] = this is the 0-4 slots that you said might be there

    My replacement then just replaces the 0-4 with the literal 4

    Also, here is some useful information that I post to people new to regular expressions. Please read and understand and follow the information under here (and that it links to).

    ----

    Please note: This Community Forum is not a data transformation service; you should not expect to be able to always say “I have data like X and want it to look like Y” and have us do all the work for you. If you are new to the Forum, and new to regular expressions, we will happily give help on the first one or two data-transformation questions, especially if they are well-asked and you show a willingness to learn; and we will point you to the documentation where you can learn how to do the data transformations for yourself in the future. But if you repeatedly ask us to do your work for you, you will find that the patience of usually-helpful Community members wears thin. The best way to learn regular expressions is by experimenting with them yourself, and getting a feel for how they work; having us spoon-feed you the answers without you putting in the effort doesn’t help you in the long term and is uninteresting and annoying for us.

    ----

    Do you want regex search/replace help? Then please be patient and polite, show some effort, and be willing to learn; answer questions and requests for clarification that are made of you. All example text should be marked as literal text using the </> toolbar button or manual Markdown syntax. To make regex in red (and so they keep their special characters like *), use backticks, like `^.*?blah.*?\z`. Screenshots can be pasted from the clipboard to your post using Ctrl+V to show graphical items, but any text should be included as literal text in your post so we can easily copy/paste your data. Show the data you have and the text you want to get from that data; include examples of things that should match and be transformed, and things that don’t match and should be left alone; show edge cases and make sure you examples are as varied as your real data. Show the regex you already tried, and why you thought it should work; tell us what’s wrong with what you do get. Read the official NPP Searching / Regex docs and the forum’s Regular Expression FAQ. If you follow these guidelines, you’re much more likely to get helpful replies that solve your problem in the shortest number of tries.



  • @astrosofista
    thank you sir!



  • @PeterJones
    I have copied your first search example that you have given me and tried it in this new search criteria. Change it a bit with no success. I got into thinking that tabs and spaces have an effect on the search.
    Thank you for the link. I read it, but it doesn’t clearly sink into my brain.
    I will search on YouTube and hope there will be examples on every code it presents.
    Thank you very much!



  • @Mark-Lozada said in YAML extension, Search 2 Value and Replace:

    Change it a bit with no success

    If you don’t tell us what you tried, we cannot help you figure out what you’re doing wrong.

    I got into thinking that tabs and spaces have an effect on the search.

    Yes, very much so.

    The answers you get are only going to be as good as the examples and description you give.

    And if @astrosofista’s works for you, just use that one. I made my regex more complex in order to make it more restrictive.

    But back to mine: If Id: isn’t actually at the beginning of the line in your real data like it was in the example you gave us, but instead has spaces or tabs before it, take the regex I gave and change every instance of ^Id: into ^\h*Id: – so FIND = (?sx) ^\h*Id: ((?!^\h*Id:).)* (Type:\h*Weapon) ((?!^\h*Id:).)* Slots:\h*\K[0-4]

    Thank you for the link. I read it, but it doesn’t clearly sink into my brain.

    Considering my post had multiple links…

    Assuming you meant you read the entirety of the npp-user-manual.org/docs/searching#regular-expressions section – there is a lot to digest there. You cannot expect to become an expert in one day. But you can look up the individual pieces in that document, and try to figure out what they are doing in this context. My description of each chunk should help with that.



  • @PeterJones

    I forgot to add the “-” on the “Id:”
    So I edited your search to:
    (?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Slots:\h*[0-4]
    This regex ((?!\-\s Id:).)* really helps a lot not jumping to the next “Id:”
    Can you tell me the difference between this regex (?s-i) to (?sx)?

    And also I noticed in my data that I have Id’s that doesn’t have a slot entry where it should have one, so I need to insert a \w with this value “Slot: 4”
    Below is the example YAML:

      - Id: 1152
        AegisName: Slayer_
        Name: Slayer
        Type: Weapon
        SubType: 2hSword
        Buy: 15000
        Weight: 1300
        Attack: 90
        Range: 1
        Slots: 3
        Jobs:
          Crusader: true
          Knight: true
          Swordman: true
        Locations:
          Both_Hand: true
        WeaponLevel: 2
        EquipLevelMin: 18
        Refineable: true
      - Id: 1153
        AegisName: Slayer__
        Name: Slayer
        Type: Weapon
        SubType: 2hSword
        Buy: 15000
        Weight: 1300
        Attack: 90
        Range: 1
        Jobs:
          Crusader: true
          Knight: true
          Swordman: true
        Locations:
          Both_Hand: true
        WeaponLevel: 2
        EquipLevelMin: 18
        Refineable: true
      - Id: 1154
        AegisName: Bastard_Sword
        Name: Bastard Sword
        Type: Weapon
        SubType: 2hSword
        Buy: 22500
        Weight: 1600
        Attack: 115
        Range: 1
        Slots: 2
        Jobs:
          Crusader: true
          Knight: true
          Swordman: true
        Locations:
          Both_Hand: true
        WeaponLevel: 2
        EquipLevelMin: 18
        Refineable: true
    

    Notice that Id:1153 is missing the Slot entry if I change the regex search to:
    (?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Range:\h*[0-4]
    and replace it with:
    (?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Slots:\h*[0-4]\rSlots:\s4
    would do duplicate Slots entry on the “Id:” that already has it



  • @Mark-Lozada said in YAML extension, Search 2 Value and Replace:

    @PeterJones

    I forgot to add the “-” on the “Id:”
    So I edited your search to:
    (?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Slots:\h*[0-4]
    This regex ((?!\-\s Id:).)* really helps a lot not jumping to the next “Id:”
    Can you tell me the difference between this regex (?s-i) to (?sx)?

    And also I noticed in my data that I have Id’s that doesn’t have a slot entry where it should have one, so I need to insert a \w with this value “Slot: 4”
    Below is the example YAML:

      - Id: 1152
        AegisName: Slayer_
        Name: Slayer
        Type: Weapon
        SubType: 2hSword
        Buy: 15000
        Weight: 1300
        Attack: 90
        Range: 1
        Slots: 3
        Jobs:
          Crusader: true
          Knight: true
          Swordman: true
        Locations:
          Both_Hand: true
        WeaponLevel: 2
        EquipLevelMin: 18
        Refineable: true
      - Id: 1153
        AegisName: Slayer__
        Name: Slayer
        Type: Weapon
        SubType: 2hSword
        Buy: 15000
        Weight: 1300
        Attack: 90
        Range: 1
        Jobs:
          Crusader: true
          Knight: true
          Swordman: true
        Locations:
          Both_Hand: true
        WeaponLevel: 2
        EquipLevelMin: 18
        Refineable: true
      - Id: 1154
        AegisName: Bastard_Sword
        Name: Bastard Sword
        Type: Weapon
        SubType: 2hSword
        Buy: 22500
        Weight: 1600
        Attack: 115
        Range: 1
        Slots: 2
        Jobs:
          Crusader: true
          Knight: true
          Swordman: true
        Locations:
          Both_Hand: true
        WeaponLevel: 2
        EquipLevelMin: 18
        Refineable: true
    

    Notice that Id:1153 is missing the Slot entry if I change the regex search to:
    (?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Range:\h*[0-4]
    and replace it with:
    (?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Slots:\h*[0-4]\rSlots:\s4
    would do duplicate Slots entry on the “Id:” that already has it

    Correction
    Search:
    ((?sx) \-\s Id: ((?!\-\s Id:).)* (Type:\h*Weapon) ((?!\-\s Id:).)* Range:\h*[0-4])
    Replace:
    \1\r\tSlots: 4



  • @Mark-Lozada ,

    I forgot to add the “-” on the “Id:” …

    Good job on figuring out a way around that.

    Can you tell me the difference between this regex (?s-i) to (?sx)?

    I thought the documentation on search modifiers section on (?enable-disable) went into that: items before the - are enabled, and items after the - are disabled; that section explains what each of the i, m, s, and x modifiers do. So (?s-i) enables s (dot matches newline) and disables i (disables case-insensitive, so makes the match case sensitive). Whereas (?sx) enables both s and x, so dot matches newline is still enabled, and ignore whitespace is enabled (so you can add extra spaces in the regex to make it more readable, but that means you have to escape literal whitespace)

    I have Id’s that doesn’t have a slot entry where it should have one

    There are ways that it could be done. But it’s getting super-complicated. Sometimes, it’s better to simplify the problem if at all possible.

    I am noticing in your data that Slots is always coming after Range (and your suggested regex with Range at the end seems to confirm that).

    I might do the missing Slots check as something simpler like “if Range isn’t followed by Slots, add Slots”.

    • FIND = Range: \d+(\s*)(?!Slots: \d+)
      • This looks for Range with an integer.
      • Then it stores the whitespace (including tabs and newlines) in group#1 – so it captures the newline plus indent between the range and the next e
      • Then it looks ahead for a tag that isn’t the number of slots
    • REPLACE = $0$1Slots: 4
      • The $0 is the entirety of the matched text from FIND
      • the $1 is the text from group#1 – this means that we add another newline and indent
      • add in the literal number of slots

    This doesn’t confirm that it’s in a Type: Weapon section. But maybe if it has a range, it will always have slots. If not, you could hybridize this idea for the replacement with what you’ve been given before to only do the replacement if there’s no Slots after Range in a Weapon.



  • @PeterJones
    I have my final search string, thanks to you sir! In order for the search to distinguish if it’s missing the “Slots” entry, I have to searched from "Range: to “Job:”

    Search:
    (Range: \d)+(\s*)(?!Slots: \d+)(\s*)Jobs:$
    Replace:
    \1 \r\n\tSlots: 4 \r\n\tJobs:


Log in to reply