Regular Expression - Regex

The purpose of this page is to provide detailed information for using Regex while editing a masterlist, as well as searching specific terms within it. Regular expressions can formally be described as follows:

A regular expression (shortened as regex or regexp) is a sequence of characters that specifies a search pattern in text.

General

Advantages of Regex

Let's take a look at DragonPriest Retexture for a first example:

The DragonPriest Retexture mod includes the two different plugins AcolyteMasks.esl and AcolyteMasks.esp. If we want to add a url for each plugin, we could write the masterlist entry like this:


  - name: 'AcolyteMasks.esl'
    url:
      - link: 'https://www.nexusmods.com/skyrimspecialedition/mods/41713/'
        name: 'DragonPriest Retexture'

  - name: 'AcolyteMasks.esp'
    url:
      - link: 'https://www.nexusmods.com/skyrimspecialedition/mods/41713/'
        name: 'DragonPriest Retexture'

This writing-style is a valid method to add metadata to the masterlists and it also means that searching for the plugin entry (e.g. AcolyteMasks.esl) is fast and easy, as it is exactly the same as the actual plugin name.

The downside to it is however, that these non-regex entries take up more space than their regex counterparts, as we have added the same link twice to the masterlist. In order to keep things maintainable, we often choose to make use of regular expressions such as the following one:

  - name: 'AcolyteMasks\.es(l|p)'
    url:
      - link: 'https://www.nexusmods.com/skyrimspecialedition/mods/41713/'
        name: 'DragonPriest Retexture'

Three different aspects have been changed respectively added in order for this regular expression to work.

  • The period . has been escaped through writing a backslash \ in front of it. This is necessary so that the period is actually recognized as such. Escaping means reducing ambiguity in a more general sense.
  • After the string es follows a capturing group ( ). The content of this capturing group needs to follow what is infront of it.
  • Inside the capturing group are the letters l and p, seperated by the OR operand |. Both letters are valid alternatives for our regex.

Both plugins AcolyteMasks.esl and AcolyteMasks.esp will now have their locations displayed in LOOT.

Regex within LOOT

Now that we taken the first step to understand what regular expressions are, it should be noted that LOOT uses three different regex implementations in different places.

  • Masterlist entry matching and the contains filter uses C++'s standard regex.
  • Condition evaluation uses the Rust regex library.
  • The search dialog uses Qt's regex implementation.

This means, that depending on where you want to use a regular expression within LOOT, unicode characters for character matching might be supported or not.

  - name: 'Example\.es(m|p)'
    msg:
      - <<: *useOnlyOneX
        subs: [ 'Example Plugin' ]
        condition: 'many("Example\.es(m|p)")'

The regex in the name field uses C++'s standard regex, which doesn't support unicode.

The regex in the condition field uses the Rust regex library, which supports unicode by default.

Regex_Search_Cards

The search dialog uses Qt's regex implementation, which doesn't support unicode characters by default (though support may be enabled in a future LOOT release).

Regex_Filter_Contain

The contains filter uses C++'s standard regex, which doesn't support unicode.

The following section will concentrate on the use of regex in the name field of plugin objects in the masterlist, so that we get a better understanding of what is possible while adding and updating plugin entries.

Characters and Rules

The following regular expressions can be used to match characters:

\d \D \w \W \s \S

In order to get a feeling what sorts of characters these expressions are capable of matching, let's take the following set of characters as reference:

Digits:

0 1 2 3 4 5 6 7 8 9

Latin Alphabet:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

Additional Latin Characters:

Ä Æ Ö Ü

Special Characters:

! # $ % & ( ) , . ' ` - ; [ ] ^ _ { } ~ € + = Œ ੩

Greek Alphabet:

α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ ς τ υ φ χ ψ ω

Japanese Hiragana:

あ い う え お か き く け こ さ し す せ そ た ち つ て と な に ぬ ね の は ひ ふ へ ほ ま み む め も や ゆ よ ら り る れ ろ わ を ん

Japanese Katakana:

ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ タ チ ツ テ ト ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ マ ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ヲ ン

Through testing the following rules could be derived:

  • \d can be used exclusively for digits 0 to 9
  • \D can be used to identify (non-digit) characters from the Latin Alphabet (except Ä Æ Ö Ü) and all the Special Characters
  • \w can be used for the digits 0 to 9, for any of the normal letters from the Latin Alphabet and for the underscore _
  • \W can detect exclusively all the special characters except the underscore _ (and no digits or Latin characters)
  • \s detects whitespace
  • \S can detect non-whitespace characters: digits, Latin characters (except additional ones) and the special characters
  • None of the expressions \d \D \w \W \S apply for the Greek and Japanese characters

Regex while Editing

Quantifiers

Once or none: ?

Exemplary masterlist entry: Map Markers Complete

  - name: 'Map Markers Complete( DLC| nC| OC)?\.esp'
    url:
      - link: 'https://www.nexusmods.com/skyrim/mods/25603/'
        name: 'Map Markers Complete'

Plugins that are identified by the above Regex:

Map Markers Complete.esp
Map Markers Complete DLC.esp
Map Markers Complete nC.esp
Map Markers Complete OC.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • After the string Map Markers Complete follows a capturing group ( ).
  • The content of the capturing group has been made optional by adding a question mark ? directly after it, so both cases of the capturing groups content being present as well as being absent are valid possible matches.
  • Inside the capturing group are the alternatives DLC, nC and OC (each string has a leading whitespace), seperated by the OR operand |.
Zero or more times: *

Exemplary masterlist entry:

  - name: 'Bashed Patch.*\.esp'
    group: *dynamicPatchGroup
    after:
      - 'SSEMerged.esp'
      - 'One ImCh Patch.esp'
      - 'One ImCh Patcher.esp'

Plugins that are identified by the above Regex:

Bashed Patch, 0.esp
Bashed Patch, 1.esp
Bashed Patch, 2.esp
...

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • After the string Bashed Patch and before the escaping of the period \. has the term .* been introduced.
  • The non-escaped period from .* is a regular expression that matches any character except the line break.
  • The asterisk * after the non-escaped period means zero or more times.
  • Therefore the above Regex matches any plugin name that begins with Bashed Patch, after which any sort and number of characters may follow, until .esp is found.

This means, that in addition to it's standard name Bashed Patch, 0.esp (and also Bashed Patch, 1.esp and Bashed Patch, 2.esp) the following variants would be found by the Regex as well:

Bashed Patch.esp
Bashed Patch_.esp
Bashed PatchAAA.esp

This goes to show that the above Regex is designed so that it may find differently named Bashed Patch plugins, even though Bashed Patch, 0.esp is and will always be the standard nomenclature for Bashed Patches.

For Wrye Bash the filename of the plugin doesn't matter to begin with, as it is identifying Bashed Patches through the plugins author field containing BASHED PATCH within it.

Also see: Wrye Bash General Readme

One or more times: +

Exemplary masterlist entry: Rich Skyrim Merchants

  - name: 'RichMerchantsSkyrim_x\d+\.esp'
    url:
      - link: 'https://www.nexusmods.com/skyrimspecialedition/mods/1772/'
        name: 'Rich Skyrim Merchants'
    tag: [ Relev ]

Plugins that are identified by the above Regex:

RichMerchantsSkyrim_x2.esp
RichMerchantsSkyrim_x5.esp
RichMerchantsSkyrim_x10.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • The character \d is used to match the digits 0 to 9.
  • The + means one or more times.
  • The Regex therefore finds RichMerchantsSkyrim_x followed by one or more digits.
Exactly x times: {x}

Exemplary masterlist entry: Enhanced Vegetation

  - name: 'Enhanced Vegetation \[\d{3}%\]\.esp'
    url: [ 'https://www.nexusmods.com/oblivion/mods/23783/' ]
    msg:
      - <<: *useOnlyOneX
        subs: [ 'Enhanced Vegetation' ]
        condition: 'many("Enhanced Vegetation \[\d{3}%\]\.esp")'

Plugins that are identified by the above Regex:

Enhanced Vegetation [100%].esp
Enhanced Vegetation [110%].esp
Enhanced Vegetation [125%].esp
Enhanced Vegetation [150%].esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • The square brackets [ and ] have been escaped as well, since otherwise they would be interpreted as a regular expression.
  • Within the square brackets is the expression \d{3} which meaning becomes exactly three digits.
  • After this expression then comes a %, which is a normal character and which is needed because the plugin names include it.
  • Notice that besides for name the regex can also be used for condition.
x or more times: {x,}

Exemplary masterlist entry:

  - name: 'Example \d{3,}\.esp'
    msg:
      - type: say
        content:
          - lang: en
            text: 'A few lines from Skyrim.ini: {0}'
          # Other languages omitted for brevity
        subs:
          - |

            ```
            [Audio]
            fMusicDuckingSeconds=6.0
            fMusicUnDuckingSeconds=8.0
            fMenuModeFadeOutTime=3.0
            fMenuModeFadeInTime=1.0
            ```

Plugins that are not identified by the above Regex:

Example 1.esp
Example 12.esp

Plugins that are identified by the above Regex:

Example 123.esp
Example 1234.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • The expression \d{3,} finds plugins that contain three or more digits.
  • In addition to the regex this example also showcases a method to display blocks of code within a message for plugins.
  • This is achieved through using the Literal Style, which is denoted by the | indicator. See yaml.org for more information.
  • The mentioned Skyrim.ini can be found in C:\Users\USER\Documents\My Games\Skyrim
x to y times (inclusive): {x,y}

Exemplary masterlist entry: Arrowsmith - Reupload | ArrowsmithES

  - name: 'Arrowsmith\w{0,2}\.esp'
    msg:
      - *alreadyInSkyRe
      - *alreadyInCompleteCraftingOverhaul

Plugins that are identified by the above Regex:

Arrowsmith.esp
ArrowsmithES.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • As described in the Rules section is the character \w used to detect the letters from the Latin alphabet, the underscore _ as well as digits 0 to 9.
  • The inclusive expression \w{0,2} therefore finds strings of length zero to two characters.
  • The plugin name from the orignal upload is Arrowsmith.esp, and the name from from the Spanish translation is ArrowsmithES.esp. The regex \w{0,2} can now detect whether or not ES is absent or present.

Character Classes

One of the characters in brackets: [ ... ]

Exemplary masterlist entry: Lanterns Of Skyrim II

  - name: '(Lanterns Of Skyrim II|LoS II - .*)\.es[mp]'
    url:
      - link: 'https://www.nexusmods.com/skyrimspecialedition/mods/30817/'
        name: 'Lanterns Of Skyrim II'

Plugins that are identified by the above Regex:

Lanterns Of Skyrim II.esm
LoS II - 3DNPC addon.esp
LoS II - BlackthornManor patch.esp
LoS II - Book of Skyrim patch.esp
LoS II - Bruma patch.esp
LoS II - Camp Argentum patch.esp
LoS II - Convenient Bridges patch.esp
LoS II - CEO Windhelm patch.esp
LoS II - ClefJ Winterhold patch.esp
LoS II - CRF patch.esp
LoS II - Camp Varglya patch.esp
LoS II - Campfire addon.esp
LoS II - Dragon Bridge patch.esp
LoS II - Darkwater Crossing patch.esp
LoS II - Eli's Breezehome patch.esp
LoS II - ELFX patch.esp
LoS II - Eli's Riverwood Shack patch.esp
LoS II - Enhanced Solitude SSE patch.esp
LoS II - ETaC patch.esp
LoS II - Fortified Whiterun patch.esp
LoS II - Falkreath patch.esp
LoS II - Helarchen Creek patch.esp
LoS II - HelgenReborn patch.esp
LoS II - Ivarstead patch.esp
LoS II - JKs Skyrim patch.esp
LoS II - JKs Riverwood patch.esp
LoS II - Karthwasten patch.esp
LoS II - Kynesgrove patch.esp
LoS II - Lantern Workers.esp
LoS II - LotD patch.esp
LoS II - Midwood Isle patch.esp
LoS II - Northern Marsh Bridges patch.esp
LoS II - Obscure College of Winterhold patch.esp
LoS II - Old Hroldan Ruins patch.esp
LoS II - Oakwood patch.esp
LoS II - Overstead SE patch.esp
LoS II - RiverwoodHuntingCabin patch.esp
LoS II - Run of the Mill Inn patch.esp
LoS II - Skyrim Bridges patch.esp
LoS II - Solitude Docks patch.esp
LoS II - Solitude Expansion patch.esp
LoS II - Settlements Expanded patch.esp
LoS II - SMIM patch.esp
LoS II - Shor's Stone patch.esp
LoS II - Sounds of Skyrim patch.esp
LoS II - Soljund's Sinkhole patch.esp
LoS II - The Fall of Granite Hill patch.esp
LoS II - TGCoR - SLaWF patch.esp
LoS II - Telengard patch.esp
LoS II - USSEP patch.esp
LoS II - Whistling Mine patch.esp
LoS II - Weathered Road Signs patch.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • The file extension is written as es[mp]. Each character in the square brackets is a valid match for the regex, so both esm and esp will be identified by it.
  • A capturing group ( ) encloses the rest of the plugin name, with the OR operand | seperating the two alternatives Lanterns Of Skyrim II and LoS II - .* within it.
  • The term .* within the second alternative consists out of the non-escaped period . (a regular expression that matches any character except the line break) and the asterisk * (which means zero or more times).
  • Therefore the term LoS II - .* matches any plugin name that begins with LoS II - after which any sort and number of characters may follow, until .es[mp] is found.

Exemplary masterlist entry: Coins of Tamriel SSE

  - name: 'Coins of Tamriel( V[234])? SSE( Hardcore)? Edition\.esp'
    url: [ 'https://www.nexusmods.com/skyrimspecialedition/mods/6441/' ]

Plugins that are identified by the above Regex:

Coins of Tamriel SSE Edition.esp
Coins of Tamriel V2 SSE Edition.esp
Coins of Tamriel V3 SSE Edition.esp
Coins of Tamriel V4 SSE Edition.esp

Coins of Tamriel SSE Hardcore Edition.esp
Coins of Tamriel V2 SSE Hardcore Edition.esp
Coins of Tamriel V3 SSE Hardcore Edition.esp
Coins of Tamriel V4 SSE Hardcore Edition.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • Six of the eight plugins include either the term V2, V3 or V4.
  • The expression V[234] will find a leading whitespace, followed by the letter V, followed by either 2,3 or 4.
  • A capturing group encloses ( V[234])? as the next step. The content of the capturing group has been made optional by adding a question mark ? directly after it, since two of the eight plugins do not include a version number in their name.
  • The expression ( Hardcore)? also has been made optional (and includes a leading whitespace), since four of the eight plugins include the word Hardcore, and the other four do not.
Range x to y: [x-y]

Exemplary masterlist entry:

  - name: 'cc[A-Z]{3}SSE[0-9]{3}.*\.es(l|m)'
    group: *ccGroup

A few examples of plugins that are identified by the above Regex:

ccBGSSSE001-Fish.esm
ccBGSSSE025-AdvDSGS.esm
ccBGSSSE037-Curios.esl
ccQDRSSE001-SurvivalMode.esl

For more information on Creation Club plugins, see UESPWiki - Creation Club.

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • The file extension is written as es(l|m), so through the use of a capturing group ( ) and the OR operand | both esl and esm are valid matches for the regex.
  • All Creation Club plugin filenames start with cc followed by a set of three varying characters from the Latin alphabet. The regular expression for that is [A-Z]{3}, so exactly three characters from the range A to Z.
  • After that all Creation Club plugins for Skyrim Special Edition include SSE in their filenames, followed by exactly three digits from the range 0 to 9. The regular expression for that is SSE[0-9]{3}.
  • After the three digits follows a hyphen - (or in a minority of cases, an underscore _) followed by a descriptive string such as Fish or SurvivalMode.
  • The regular expression .* matches these strings, so the non-escaped period . which finds all characters except the line break, and the asterisk * that means zero or more.
One character that is not x: [^x]

Exemplary masterlist entry:

    - &scriptExtenderMissing
      type: error
      content: 'You have installed an {0} plugin but {0} was not found! See {0} download page: {1}.'
      subs:
        - 'SKSE'
        - '[SKSE](https://skse.silverlock.org)'
      condition: 'file("SKSE/Plugins/([^\.]+\.dll)") and not file("../skse_loader.exe")'

Here is a small overview of SKSE Plugins which are identified by the above Regex (this list does not claim to be complete):

SKSE Plugin Mod
AHZmoreHUDPlugin.dll moreHUD
BugFixPlugin.dll Bug fixes
chargen.dll RaceMenu
ConsolePlugin.dll ConsoleUtil
CopyPaste.dll Copy and Paste in Console
CrashFixPlugin.dll Crash fixes
DisplayEnemyLevel.dll Display Enemy Level
DoubleJumpPlugin.dll Better Jumping
DynamicAnimationReplacer.dll Dynamic Animation Replacer
fiss.dll FileAccess Interface for Skyrim Script - FISS
FloatingDamage.dll Floating Damage
havok_fix.dll (SKSE) Havok Fix
LipSyncFix.dll Fix Lip Sync
LocationalDamage.dll Locational Damage
nioverride.dll RaceMenu
PlayerRotation.dll Player Rotation in ShowRaceMenu
po3_namedashpiles.dll Name Those Ash Piles
po3_papyrusextender.dll powerofthree's Papyrus Extender
po3_SpellPerkItemDistributor.dll Spell Perk Item Distributor
po3_WashThatBloodOff.dll Wash That Blood Off
QuickLoot.dll Quick Loot
SkyrimSouls.dll SkyrimSouls - Unpaused Game Menus
StorageUtil.dll Campfire - Complete Camping System

Summary:

  • The condition in this example includes the regular expression: file("SKSE/Plugins/([^\.]+\.dll)")
  • The objective is to find .dll files within the folder structure SKSE/Plugins/.
  • As a first step the period . in front of dll has been escaped through writing a backslash \ in front of it.
  • The remaining part of the regex [^\.]+ consists out of three parts.
  • [^x] will find a character that is not x, which is achieved by placing the circumflex ^ within square brackets [ ]. In this case x is an escaped period \. so not a period is what we want. After the square brackets comes the quantifier plus + which means one or more times.
  • Therefore the regular expression [^\.]+\.dll finds all SKSE plugins, which filesnames include one or more characters that are not a period, and end with .dll

Lookarounds

Negative lookahead: (?! ...)

Exemplary masterlist entry: Kalilies NPCs

  - name: '.*(KaliliesNPC|Kalilies NPC)(?! WARP).*\.esp'
    url: [ 'https://www.nexusmods.com/skyrimspecialedition/mods/30247/' ]

Plugins that are identified by the above Regex:

AI Overhaul - KaliliesNPCs Patch.esp
CRF - Kalilies NPC's Patch.esp
KaliliesNPCs.esp
KaliliesNPCs - CRF patch.esp
KaliliesNPCs - USSEP CRF AI Overhaul Patch.esp
Kalilies NPCs + AI Overhaul + Cutting Room Floor Patch.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • Two capturing groups ( )( ) enclose different parts of the target filenames.
  • Before and after the two capturing groups is the regular expression .* (the non-escaped period . matches all characters except the line break, and the asterisk * means zero or more). Placing these before and after the two capturing groups ensures, that around the central strings KaliliesNPC and Kalilies NPC any sort and number of characters is matched and found.
  • Inside the first capturing group is the OR operand | so that both KaliliesNPC and Kalilies NPC and valid matches.
  • Inside the second capturing group is the negative lookahead ?! WARP to exclude any search results that contain WARP in the filename. This is necessary, since otherwise there is a false positive search result in the form of KaliliesNPCs WARP PATCH.esp from Kalilies NPCs WARP patch. Since it is the purpose of this regex to provide a url for the plugins from the original mod page, and not for the plugin(s) from other mod pages, this is an important and efficient method to achieve the outlined purpose.
  • It should be noted, that support for lookaround varies by implementation and in LOOT negative lookahead is supported everywhere apart from inside conditions.

More Examples

Requiem

Exemplary masterlist entry: Requiem - The Roleplaying Overhaul

  - name: 'Requiem( - (No (Overencumbered )?Messages|Restored (Rewarding Sounds|Saving Messages)|Vanilla Dragonborn DLC))?\.esp'
    url:
      - link: 'https://www.nexusmods.com/skyrim/mods/19281/'
        name: 'Requiem - The Roleplaying Overhaul'

Plugins that are identified by the above Regex:

Requiem.esp
Requiem - No Messages.esp
Requiem - No Overencumbered Messages.esp
Requiem - Restored Rewarding Sounds.esp
Requiem - Restored Saving Messages.esp
Requiem - Vanilla Dragonborn DLC.esp

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • This regular expression is characterized by the fact that it uses multiple capturing groups that are nested into one another.
  • The outer capturing group ( ) comes directly after Requiem and it's content it made optional through adding the question mark ? directly after it.
  • Within this outer capturing group we have the following situation: - (a|b|c) with a, b and c being three alternatives seperated by | - the OR operand.
  • a is No (Overencumbered )?Messages and it has it's own capturing group with the optional content Overencumbered .
  • b is Restored (Rewarding Sounds|Saving Messages) and it too has it's own capturing group with the non-optional content Rewarding Sounds|Saving Messages.
  • c is Vanilla Dragonborn DLC
Skyrim Project Optimization

Exemplary masterlist entry: Skyrim Project Optimization SE

  - name: 'Skyrim Project Optimization - (No Homes - )?Full( ESL)? Version\.esm'
    url:
      - link: 'https://www.nexusmods.com/skyrimspecialedition/mods/14084/'
        name: 'Skyrim Project Optimization SE'

Plugins that are identified by the above Regex:

Skyrim Project Optimization - Full ESL Version.esm
Skyrim Project Optimization - Full Version.esm
Skyrim Project Optimization - No Homes - Full ESL Version.esm
Skyrim Project Optimization - No Homes - Full Version.esm

Summary:

  • The period . has been escaped through writing a backslash \ in front of it.
  • All four plugins start with Skyrim Project Optimization - and as such, so does the regex.
  • Two of the four plugins continue on with No Homes - and the regex accounts for that with the optional capturing group: (No Homes - )?
  • Then all four plugins continue with Full and so does the regex.
  • Two of the four plugins continue on with ESL and the regex accounts for that with the optional capturing group: ( ESL)?
  • All four plugin names and as such the regex end with Version and the file extension.

Regex while Searching

General

The LOOT masterlists are .yaml files that include thousands of lines and data for many different plugins. Sometimes and for specific reasons we found it useful to make use of regular expressions while searching different terms within the masterlists.

For example, in Notepad++ you can switch from the Search Mode Normal to Regular expression to use the following examples.

Notepad_Regex_01

Examples

Find - name: '' entries followed by url

Regular Expression:

- name: '\w{1,}\.\w{3}'\r?\n.*url

Exemplary search result:

  - name: 'SimSettlements.esm'
    url: [ 'https://www.nexusmods.com/fallout4/mods/21872' ]
    after:
      - 'HUDFramework.esm'
      - 'WorkshopFramework.esm'

Summary:

  • - name: '\w{1,}\.\w{3}' is the first part of the regex.
  • Within the two apostrophes '' the expression \w{1,} searches for one or more characters of any sort (latin alphabet, digits 0 to 9 and the underscore _), the escaped period \. marks the point the file extension begins and \w{3} is used to find exactly three characters for the file extension (which can either be esm, esp or esl).
  • The next part of the regex is \r?\n.
  • The combination \r\n of the carriage return (CR) character \r and the line feed (LF) character \n act together as mechanism to detect a new line of text. It is important to know that while the Windows-style new line consists out of CR LF, files in Git are usually saved with just LF. To ensure that the above regex works in both invironments the question mark ? has been added directly after \r to make it optional.
  • The last part of the regex is .*url.
  • It consists out of the non-escaped period . which matches all characters except the line break, the asterisk * which means zero or more and the string url.
  • The full regex is therefore able to find plugin entries, where directly after the - name: '' line the location data with a url follows.
Find - name: '' entries not followed by url

Regular Expression:

- name: '\w{1,}\.\w{3}'\r?\n.*(after|clean|dirty|^display|group|inc|msg|req)

Exemplary search result:

  - name: 'PPF.esm'
    clean:
      # English
      - crc: 0x92CA557D
        util: 'FO4Edit v4.0.4b'

Summary:

  • - name: '\w{1,}\.\w{3}'\r?\n.* is exactly the same as in the above regex. The only difference is that instead of url now the capturing group (after|clean|dirty|^display|group|inc|msg|req) is used.
  • Inside the capturing group ( ) are the different & alternative keys from the masterlists seperated by the OR operand |, so that every other one except the url is found.
  • The circumflex ^ is in front of display, because detail is never found directly under the main name key of a plugin entry.

If the display key would not be excluded, false positive search results such as the following one would be found:

  - name: 'SS2.esm'
    url:
      - link: 'https://www.nexusmods.com/fallout4/mods/47976/'
        name: 'Sim Settlements 2 (Nexus Mods)'
      - link: 'https://bethesda.net/en/mods/fallout4/mod-detail/4183663/'
        name: 'Sim Settlements 2 (Bethesda.net Mods)'
    inc:
      - name: 'Conquest.esp'
        display: 'Conquest - Build New Settlements and Camping'
Find instances of trailing whitespaces after - name: ''

Regular Expression:

- name: '\w{1,}\.\w{3}'\s$

Exemplary search result (notice the whitespace at the end):

  - name: 'Homemaker.esm'
    url: [ 'https://www.nexusmods.com/fallout4/mods/1478/' ]

What is not found:

  - name: 'Homemaker.esm'
    url: [ 'https://www.nexusmods.com/fallout4/mods/1478/' ]

Summary:

  • - name: '\w{1,}\.\w{3}' is exactly the same as in the above regex.
  • The potential whitespace is found by \s and after that the dollar sign $ is used to find the end of the line.
Find instances of single line location data

Regular Expression:

url:\s\[

Exemplary search result:

  - name: 'SettlementKeywords.esm'
    url: [ 'https://www.nexusmods.com/fallout4/mods/12226/' ]

What is not found:

  - name: 'ColterFix.esp'
    url:
      - link: 'https://www.nexusmods.com/fallout4/mods/59323/'
        name: 'Overboss Colter Fix'

Summary:

  • The regex starts with url:, followed by \s to detect whitespace.
  • After that the opening square bracket is escaped.
Find plugins with x dirty edits

Regular Expression:

\w{3}: \d{x}

Exemplary search result for x = 4:

  - name: 'Little Cottage on a Hill.esp'
    url:
      - link: 'https://www.nexusmods.com/skyrim/mods/22773/'
        name: 'Little Cottage on a Hill'
    dirty:
      # v1.0
      - <<: *reqManualFix
        crc: 0xAB8573E8
        util: '[TES5Edit v4.0.4b](https://www.nexusmods.com/skyrim/mods/25859)'
        itm: 2733
        udr: 44
        nav: 1

Summary:

  • The regex \w{3}: \d{4} follows the way cleaning data is added to the masterlist.
  • First exactly three characters are searched through \w{3} which in the masterlist in this context can be either itm, udr or nav, after which a colon : follows.
  • After that an exactly four digit long number is searched (including a leading whitespace) through \d{4}. In this example itm: 2733 has been found.
Find Creation Club plugins

Regular Expressions:

cc\w{3}sse\d{3}

cc\w{3}fo4\d{3}

Exemplary search results:

  - name: 'ccfsvsse001-backpacks.esl'
    clean:
      - crc: 0x3F8D2754
        util: 'SSEEdit v4.0.4'

  - name: 'ccbgsfo4076-pipmystery.esl'
    clean:
      - crc: 0x3FAFF472
        util: 'FO4Edit v4.0.2j'

Summary:

  • All Creation Club plugin filenames start with cc followed by a set of three varying characters from the Latin alphabet. The regular expression to match these three characters is \w{3}.
  • After that all Creation Club plugins for Skyrim Special Edition include sse in their filenames, followed by exactly three digits from the range 0 to 9. The regular expression for that is sse\d{3}.
  • For the Fallout 4 Creation Club plugins the next set of characters ist fo4 in most cases, and in minority of cases it is f04, followed by exactly three digits from the range 0 to 9. The regular expression for that is fo4\d{3}, though this expression will not find the ones with f04.
  • After the three digits follows a hyphen - (or in a minority of cases, an underscore _) followed by a descriptive string such as backpacks or pipmystery. Our regex isn't interested in that part however, as it isn't really necessary in order to find the Creation Club plugins - it's good enough already.
  • As a more general approach, cc\w{6}\d{3} could also be used, and this variation should find all Creation Club plugins from both Skyrim Special Edition and Fallout 4.
  • You could generalise it even more to cc\w{9} as \w in addition to characters from the latin alphabet & the underscore also finds digits. However, this approach would also easily find false positives such as konahrik_accoutrements.esp.
Find block style single-element lists

Lists that have only one element that aren't written in flow style can look like the after tag in the following example:

  - name: 'InnoLostAlt.esp'
    url: [ 'https://www.nexusmods.com/skyrimspecialedition/mods/24236' ]
    after:
      - 'TheChoiceIsYours.esp'
    clean:
      - crc: 0x7D8AB5D7
        util: 'SSEEdit v4.0.3'

For consistency reasons we instead write these list like this:

    after: [ 'TheChoiceIsYours.esp' ]

The following regular expression can be used to find such instances:

: *\r?\n {3,}-.*\r?\n {2,4}(?! )

Additional exemplary search results:

  - name: 'after_clean.esp'
    after:
      - 'TheChoiceIsYours.esp'
    clean:

  - name: 'msg_clean_1.esp'
    msg:
      - *includesMBBF
    clean:

  - name: 'msg_clean_2.esp'
    msg:
      - <<: *patchRequiem3rdParty
        condition: 'not checksum("Rebirth Monster.esp", 3F7371A1)'
        subs:
          - '[Revenge of the Enemies Patches](https://www.nexusmods.com/skyrim/mods/73369)'
    clean:

  - name: 'tag_clean.esp'
    tag:
      - Stats
    clean:

Summary:

  • Finds most occurrences, taking advantage of the expected indentation of such elements & how it will be preceded by a colon & newline & followed by a less indented line.
  • The regex starts with : *\r?\n to find a colon : after which a whitespace and the asterisk * follow to indicate zero or more whitespaces after the colon. After that \r?\n is used to find an immediately following end of the line. This is done so that for example after: can be matched, after which then the potential single-element list could follow in the next line.
  • The next step is to find a hyphen - in the next line of text using {3,}-. For this we use a whitespace followed by the quantifier {3,} which as such searches three or more whitespaces, followed by the hyphen -.
  • After that we continue with .* to find zero or more of characters the non-escaped period (any character except line break) may find after the hyphen (e.g. 'TheChoiceIsYours.esp') and follow that up with \r?\n to find the end of the second line.
  • The final step is to use {2,4}(?! ) for what comes after the single-element lists. First we use {2,4} to indicate two to four whitespaces followed by a negative lookahead (?! ) to rule out any matches with additional whitespaces in this line. A clean tag indented by four spaces would fulfill this check.

While this regex is already great in finding single-element lists, it wouldn't find these instances:

  - name: 'after_without_clean.esp'
    after:
      - 'TheChoiceIsYours.esp'

  - name: 'msg_without_clean.esp'
    msg:
      - *includesMBBF

  - name: 'tag_without_clean.esp'
    tag:
      - Stats

The expression can be improved to find these instances as well:

: *\r?\n {3,}-.*\r?\n( {2,4}(?! )|\r?\n+)
  • {2,4}(?! ) has been placed inside a capturing group ( ) as the first alternative.
  • Within this capturing group are two alternatives, seperated by the OR operand | and the second alternative is \r?\n+ which aim is to find one or more new lines after the second line.

While the improved regex already finds all of the above examples, it also finds the following case, which is a false positive search result:

  - name: 'Example \d{3,}\.esp'
    msg:
      - type: say
        content:
          - lang: en
            text: 'A few lines from Skyrim.ini: {0}'
          # Other languages omitted for brevity
        subs:
          - |

            ```
            [Audio]
            fMusicDuckingSeconds=6.0
            fMusicUnDuckingSeconds=8.0
            fMenuModeFadeOutTime=3.0
            fMenuModeFadeInTime=1.0
            ```

The regex can once again be improved to exclude the above false positive:

: *\r?\n {3,}-[^\r?\n|]*\r?\n( {2,4}(?! )|\r?\n+)
  • Instead of the non-escaped period in -.* we now use -[^\r?\n|]* to exclude the | character in the next line.
  • This is achieved through searching one character that is not x with [^x] and x being \r?\n|.
Revisit merger bash tags

Regular Expressions:

(\[|-|:) *(Actors\.Perks|Invent|Outfits|(R\.)?Relations|Derel)

Exemplary search results:

  - name: 'DeadMoney.esm'
    tag:
      - Deflst
      - Invent.Add
      - Invent.Remove

  - name: 'KDS Wearable Backpacks.esp'
    tag: [ Invent ]

  - name: 'NewVegasBountiesII.esp'
    tag: [ Relations ]

Summary:

  • Relevant use case: Revisit merger tags for WB v310
  • The regex (\[|-|:) is meant to be read as (a|b|c), so as a capturing group ( ) where three alternatives are seperated with the OR operand |.
  • In this example, a would be the escaped opening square bracket [, b would be a hyphen - and c would be the colon :
  • After the capturing group and before the other tags follows a whitespace and an asterisk * to search for zero or more whitespaces.
  • Another capturing group (Actors\.Perks|Invent|Outfits|(R\.)?Relations|Derel) is used to search for the different tags that should be reevaluated at a later date.
Find NoMerge bash tags

Regular Expressions:

(\[|-|:) *NoMerge

Exemplary search results:

  - name: 'FNVMerged.esp'
    tag: [ NoMerge ]

  - name: 'Realistic Weight.esp'
    tag:
      - NoMerge
      - Stats

What is not found:

bash_tags:
  - 'NoMerge'

# NoMerge

Summary:

  • Relevant use case: Revisit mods with NoMerge tag for WB v311+
  • The regex (\[|-|:) is meant to be read as (a|b|c), so as a capturing group ( ) where three alternatives are seperated with the OR operand |.
  • In this example, a would be the escaped opening square bracket [, b would be a hyphen - and c would be the colon :
  • After the capturing group and before the NoMerge tag follows a whitespace and an asterisk * to search for zero or more whitespaces.

Find & Replace

General

Find & Replace is a feature of e.g. Notepad++ as well as VSCode, to easily find a specific term and replace it with another, with a single button press.

This presents a great possibility to go through larger tasks that otherwise would need a lot of manual work, however masterlist maintainers should refrain from using automated Replace All functions.

This would certainly decrease the time needed to work on the task at hand, however it would also come with an elevated risk to miss something or replace some parts that weren't intended to be replaced.

Examples

Replace file extension
Find:
.esp

Replace:
.esl

Summary:

  • This regex is able to easily replace .esp file extensions to .esl.
Replace Invent Bash Tag
Find:
\s{6}-\sInvent$

Replace:
      - Test

Summary:

  • Replaces the Bash Tag Invent with Test.
  • While searching for whitespaces can be done with the regular expression \s, replacing them must be done the normal way.
  • This means that any number of whitespaces that have been found through a regex (e.g. \s{6}), must be typed individually within the Replace field.
  • The end of the line is detected with the dollar sign $.
Add missing trailing slashes to Nexus Mods url
Find:
/mods/(\d{1,})'

Replace:
/mods/\1/'

Exemplary search result:

  - name: 'Altitude.esp'
    url: [ 'https://www.nexusmods.com/newvegas/mods/71404' ]

Replacement:

  - name: 'Altitude.esp'
    url: [ 'https://www.nexusmods.com/newvegas/mods/71404/' ]

Summary:

  • \d{1,} is used to detect one or more digits, to match the mod page number in the link, e.g. 71404.
  • This expression is then placed within a capturing group ( ), so that the Replace Field has access to it.
  • After the capturing group comes an apostrophe ' to detect the end of the link that has no trailing slash.
  • \1 in the Replace field copies the contents of the first capturing group over from the Find field (in this case there is only one).
  • As the last step comes /' after \1 to add the trailing slash.
Update location data to include a name
Find:
\s{4}url: \[\s(.*)\s\]

Replace:
    url:\r\n      - link: \1\r\n        name: ''
Notepad_Regex_02

Exemplary search result:

  - name: 'Altitude.esp'
    url: [ 'https://www.nexusmods.com/newvegas/mods/71404/' ]

Replacement:

  - name: 'Altitude.esp'
    url:
      - link: 'https://www.nexusmods.com/newvegas/mods/71404/'
        name: ''

Summary:

  • Any whitespaces have been added individually within the Replace field.
  • \1 in the Replace field copies the contents of the first capturing group over from the Find field (in this case there is only one).